[
  {
    "path": ".codecov.yml",
    "content": "---\ncoverage:\n  status:\n    project:\n      default:\n        target: auto\n        threshold: 1\n        base: auto\n    patch: off\ncomment: false\nignore:\n  - \"!autoload/go/*.vim$\"\n  - \"autoload/go/*_test.vim$\"\n"
  },
  {
    "path": ".coveragerc",
    "content": "[run]\nplugins = covimerage\ndata_file = .coverage_covimerage\n"
  },
  {
    "path": ".dockerignore",
    "content": ".local/\n.config/\n.cache/\n.dlv/\n.git/\n.viminfo\nissues/\nautoload/go/**/pkg/\n"
  },
  {
    "path": ".editorconfig",
    "content": "# http://EditorConfig.org\n\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\ntrim_trailing_whitespace = true\n\n[*.go]\nindent_style = tab\nindent_size = 4\n\n[Makefile]\nindent_style = tab\nindent_size = 8\n"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "content": "Thanks for improving vim-go! Before you dive in please read the following:\n\n1. Please read our\n   [Documentation](https://github.com/fatih/vim-go/blob/master/doc/vim-go.txt),\n   it might have a solution to your problem.\n2. If you add a new feature then please don't forget to update the documentation:\n   [doc/vim-go.txt](https://github.com/fatih/vim-go/blob/master/doc/vim-go.txt).\n3. If it's a breaking change or exceeds 100 lines of code then please open an\n   issue first and describe the changes you want to make.\n4. See `:help go-development` for instructions on how to run and write tests. If\n   you add a new feature be sure you also include a test if feasible.\n\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "patreon: bhcleek\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "---\nblank_issues_enabled: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/default.md",
    "content": "---\nname: Bug Report\nabout: Use this template for all issues\n---\n<!--\nBefore filing an issue, please check if vim-go's help addresses your problem (see `:help go-troubleshooting`).\n\nConsider executing `:GoReportGitHubIssue` to populate much of this information automatically.\n-->\n### What did you do? (required: The issue will be **closed** when not provided)\n\n<!--\nIf possible, please provide clear steps for reproducing the problem.\n-->\n\n### What did you expect to happen?\n\n### What happened instead?\n\n### Configuration (**MUST** fill this out):\n\n#### vim-go version:\n\n####  `vimrc` you used to reproduce:\n<!--\nUse a *minimal* vimrc with other plugins disabled; do not link to a 2,000 line vimrc.\n\nIf this is not provided or is obviously incomplete, the issue may be unceremoniously closed.\n-->\n<!-- vimrc -->\n<details><summary>vimrc</summary>\n\n```vim\n\n```\n</details>\n\n#### Vim version (first three lines from `:version`):\n<!-- :version -->\n\n#### Go version (`go version`):\n<!-- go version -->\n\n#### Go environment\n<details><summary><code>go env</code> Output:</summary><br><pre>\n<!-- go env -->\n\n</pre></details>\n\n#### gopls version\n<details><summary><code>gopls version</code> Output:</summary><br><pre>\n<!-- gopls version -->\n\n</pre></details>\n"
  },
  {
    "path": ".github/issue_template.md",
    "content": "---\nname: Bug Report\nabout: Use this template for all issues\n---\n<!--\nBefore filing an issue, please check if vim-go's help addresses your problem (see `:help go-troubleshooting`).\n\nConsider executing `:GoReportGitHubIssue` to populate much of this information automatically.\n-->\n### What did you do? (required: The issue will be **closed** when not provided)\n\n<!--\nIf possible, please provide clear steps for reproducing the problem.\n-->\n\n### What did you expect to happen?\n\n### What happened instead?\n\n### Configuration (**MUST** fill this out):\n\n#### vim-go version:\n\n####  `vimrc` you used to reproduce:\n<!--\nUse a *minimal* vimrc with other plugins disabled; do not link to a 2,000 line vimrc.\n\nIf this is not provided or is obviously incomplete, the issue may be unceremoniously closed.\n-->\n<!-- vimrc -->\n<details><summary>vimrc</summary>\n\n```vim\n\n```\n</details>\n\n#### Vim version (first three lines from `:version`):\n<!-- :version -->\n\n#### Go version (`go version`):\n<!-- go version -->\n\n#### Go environment\n<details><summary><code>go env</code> Output:</summary><br><pre>\n<!-- go env -->\n\n</pre></details>\n\n#### gopls version\n<details><summary><code>gopls version</code> Output:</summary><br><pre>\n<!-- gopls version -->\n\n</pre></details>\n"
  },
  {
    "path": ".github/workflows/git.yml",
    "content": "name: git checks\non: [pull_request]\n\njobs:\n  autosquash-commits-integrated:\n    runs-on: ubuntu-22.04\n\n    steps:\n    - uses: actions/checkout@v2.0.0\n    - name: Block Fixup Commit Merge\n      uses: 13rac1/block-fixup-merge-action@v2.0.0\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: test\non: [push, pull_request]\njobs:\n  lint:\n    name: lint\n    runs-on: ubuntu-22.04\n    steps:\n    - name: set up python\n      uses: actions/setup-python@v5.5.0\n      with:\n        python-version: 3.7\n    - name: install vim-vint\n      run: |\n        python -m pip install --upgrade pip\n        pip install vim-vint pathlib\n    - name: checkout\n      uses: actions/checkout@v2.1.0\n    - name: install vim\n      run: $GITHUB_WORKSPACE/scripts/install-vim vim-9.1\n    - name: install tools\n      run: $GITHUB_WORKSPACE/scripts/install-tools vim-9.1\n    - name: lint\n      run: $GITHUB_WORKSPACE/scripts/lint vim-9.1\n  test:\n    name: test\n    runs-on: ubuntu-22.04\n    strategy:\n      fail-fast: false\n      matrix:\n        go: ['1.25','1.26']\n        vim: ['vim-8.2', 'vim-9.1', 'nvim']\n    steps:\n    - name: setup Go\n      uses: actions/setup-go@v2.1.3\n      with:\n        go-version: ${{ matrix.go }}\n    - name: set up python\n      uses: actions/setup-python@v5.5.0\n      with:\n        python-version: 3.7\n    - name: install covimerage\n      run: |\n        python -m pip install --upgrade pip\n        pip install click==7.1.2 covimerage==0.2.1 codecov pathlib\n    - name: checkout\n      uses: actions/checkout@v2.1.0\n    - name: install vim\n      run: $GITHUB_WORKSPACE/scripts/install-vim ${{ matrix.vim }}\n    - name: install tools\n      run: $GITHUB_WORKSPACE/scripts/install-tools ${{ matrix.vim }}\n    - name: test\n      run: $GITHUB_WORKSPACE/scripts/test -c ${{ matrix.vim }}\n    - uses: codecov/codecov-action@v1\n      with:\n        # token is not required for public repos\n        #token: ${{ secrets.CODECOV_TOKEN }}\n        file: $GITHUB_WORKSPACE/coverage.xml\n        flags: unittests\n        name: vim-go\n        fail_ci_if_error: false\n"
  },
  {
    "path": ".gitignore",
    "content": "*.pyc\n.DS_Store\n/.bash_history\n/.cache\n/.config\n/.coverage.covimerage\n/.local\n/.viminfo\n/coverage.xml\n/doc/tags\n/issues\n"
  },
  {
    "path": ".vintrc.yaml",
    "content": "policies:\n  ProhibitUnnecessaryDoubleQuote:\n    enabled: false\n  ProhibitEqualTildeOperator:\n    enabled: false\n  ProhibitNoAbortFunction:\n    enabled: false\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "## unplanned\n\nBACKWARDS INCOMPATIBILITIES:\n* Update golangci-lint support to expect golangci-lint/v2.\n  [[GH-3710]](https://github.com/fatih/vim-go/pull/3710)\n\nIMPROVEMENTS:\n\nBUG FIXES:\n* Fix delay when listing breakpoints when stepping in Neovim.\n  [[GH-3714]](https://github.com/fatih/vim-go/pull/3714)\n* Fix :GoReportGitHubIssue after GitHub changed template URL behaviors.\n  [[GH-3736]](https://github.com/fatih/vim-go/pull/3736)\n* Add support for GNUMakefile to compiler settings.\n  [[GH-3723]](https://github.com/fatih/vim-go/pull/3723)\n* Bring back go-callers mappings, its documentation, and :GoCallers\n  documentation.\n  [[GH-3741]](https://github.com/fatih/vim-go/pull/3741)\n\n\n## v1.29 - (April 18, 2025)\n\nBACKWARDS INCOMPATIBILITIES:\n* Drop support for [guru](https://docs.google.com/document/d/1_Y9xCEMj5S-7rv2ooHpZNH15JgRT5iM742gJkw5LtmQ/edit?pli=1&tab=t.0#heading=h.ojv16z1d1gas).\n  [[GH-3650]](https://github.com/fatih/vim-go/pull/3650)\n  [[GH-3654]](https://github.com/fatih/vim-go/pull/3654)\n* Drop support for `keyify`.\n  [[GH-3665]](https://github.com/fatih/vim-go/pull/3665)\n\nIMPROVEMENTS:\n* Change the group that godebugStracktrace is default linked to.\n  [[GH-3483]](https://github.com/fatih/vim-go/pull/3483)\n* Add `:GoCoverageOverlay`.\n  [[GH-3485]](https://github.com/fatih/vim-go/pull/3485)\n* Add `:GoTestFile`.\n  [[GH-3486]](https://github.com/fatih/vim-go/pull/3486)\n  [[GH-3487]](https://github.com/fatih/vim-go/pull/3487)\n* Add `(go-fill-struct)` mapping.\n  [[GH-3502]](https://github.com/fatih/vim-go/pull/3502)\n  [[GH-3503]](https://github.com/fatih/vim-go/pull/3503)\n* Output an error message when `g:go_fillstruct_mode` and `g:go_gopls_enabled`\n  conflict.\n  [[GH-3504]](https://github.com/fatih/vim-go/pull/3504)\n* Add `:GoExtract` command and related mapping.\n  [[GH-3506]](https://github.com/fatih/vim-go/pull/3506)\n  [[GH-3617]](https://github.com/fatih/vim-go/pull/3617)\n  [[GH-3626]](https://github.com/fatih/vim-go/pull/3626)\n* Halt the debugger after a connection is establish with `:GoDebugConnect`.\n  [[GH-3514]](https://github.com/fatih/vim-go/pull/3514)\n  [[GH-3520]](https://github.com/fatih/vim-go/pull/3520)\n  [[GH-3570]](https://github.com/fatih/vim-go/pull/3570)\n* Clarify `:GoImpl` usage message.\n  [[GH-3522]](https://github.com/fatih/vim-go/pull/3522)\n* Add commands and mappings related to godoc to the godoc preview window.\n  [[GH-3527]](https://github.com/fatih/vim-go/pull/3527)\n  [[GH-3532]](https://github.com/fatih/vim-go/pull/3532)\n  [[GH-3559]](https://github.com/fatih/vim-go/pull/3559)\n* Link goPredefinedIdentifiers to Constant instead of goBoolean by default.\n  [[GH-3528]](https://github.com/fatih/vim-go/pull/3528)\n* Add `gD` mapping for `:GoDefType`.\n  [[GH-3531]](https://github.com/fatih/vim-go/pull/3531)\n* Use Vim's native tag stack when possible.\n  [[GH-3548]](https://github.com/fatih/vim-go/pull/3548)\n  [[GH-3554]](https://github.com/fatih/vim-go/pull/3554)\n  [[GH-3556]](https://github.com/fatih/vim-go/pull/3556)\n  [[GH-3557]](https://github.com/fatih/vim-go/pull/3557)\n  [[GH-3558]](https://github.com/fatih/vim-go/pull/3558)\n* Update codeAction response handling to work with gopls v0.12.0.\n  [[GH-3555]](https://github.com/fatih/vim-go/pull/3555)\n* Drop support for Vim 8.0.\n  [[GH-3538]](https://github.com/fatih/vim-go/pull/3538)\n* Set gopls clientInfo field.\n  [[GH-3567]](https://github.com/fatih/vim-go/pull/3567)\n* Add support for the Go 1.21's new builtin functions.\n  [[GH-3578]](https://github.com/fatih/vim-go/pull/3578)\n* Add syntax support for the toolchain directive in go.mod.\n  [[GH-3633]](https://github.com/fatih/vim-go/pull/3633)\n* Add fuzz snippet.\n  [[GH-3636]](https://github.com/fatih/vim-go/pull/3636)\n* Update gopls code action handling.\n  [[GH-3695]](https://github.com/fatih/vim-go/pull/3695)\n* Remove installation of `gorename`.\n  [[GH-3697]](https://github.com/fatih/vim-go/pull/3697)\n* Add support for `gopls rename`.\n  [[GH-3698]](https://github.com/fatih/vim-go/pull/3698)\n* Use a double border around doc popup.\n  [[GH-3705]](https://github.com/fatih/vim-go/pull/3705)\n\n\nBUG FIXES:\n* Update [impl](https://github.com/josharian/impl) source path after its default branch was changed from master to main.\n  [[GH-3477]](https://github.com/fatih/vim-go/pull/3477)\n* Update `:GoMetaLinter` help.\n  [[GH-3534]](https://github.com/fatih/vim-go/pull/3534)\n* Update syntax file for empty const, var, and import lists.\n  [[GH-3577]](https://github.com/fatih/vim-go/pull/3577)\n  [[GH-3579]](https://github.com/fatih/vim-go/pull/3579)\n* Fix sameids highlighting when id is preceded with multi-byte characters.\n  [[GH-3587]](https://github.com/fatih/vim-go/pull/3587)\n* Avoid creating an anonymous snippet when selected completion lacks\n  placeholders.\n  [[GH-3603]](https://github.com/fatih/vim-go/pull/3603)\n* Fix sameids highlighting when identifier immediately precedes newline.\n  [[GH-3606]](https://github.com/fatih/vim-go/pull/3606)\n* Fix Python escape sequence in UltiSnips/go.snippets.\n  [[GH-3614]](https://github.com/fatih/vim-go/pull/3614)\n* Do not attempt to use gopls for documentation when gopls is disabled.\n  [[GH-3610]](https://github.com/fatih/vim-go/pull/3610)\n* Fix spelling of go#util#EchoWarning in a few calls.\n  [[GH-3613]](https://github.com/fatih/vim-go/pull/3613)\n* Improve matching of package comments.\n  [[GH-3637]](https://github.com/fatih/vim-go/pull/3637)\n* Fix editing of lines with multibyte characters.\n  [[GH-3644]](https://github.com/fatih/vim-go/pull/3644)\n* Swallow delve errors when trying to place a breakpoint at an invalid location.\n  [[GH-3652]](https://github.com/fatih/vim-go/pull/3652)\n* Fix parsing of gopls error message to determine debug port.\n  [[GH-3672]](https://github.com/fatih/vim-go/pull/3672)\n* Handle unexpected code action commands from `gopls`.\n  [[GH-3678]](https://github.com/fatih/vim-go/pull/3678)\n* Fix substitution paths in debug stacktrace window.\n  [[GH-3675]](https://github.com/fatih/vim-go/pull/3675)\n* Fix handling of gopls restarts.\n  [[GH-3685]](https://github.com/fatih/vim-go/pull/3685)\n* Fix :GoDocBrowser's handling of arguments.\n  [[GH-3703]](https://github.com/fatih/vim-go/pull/3703)\n\n## v1.28 - (December 17, 2022)\n\nBUG FIXES:\n* Remove diagnostic message used during development.\n  [[GH-3476]](https://github.com/fatih/vim-go/pull/3476)\n\n## v1.27 - (December 17, 2022)\n\nBACKWARDS INCOMPATIBILITIES:\n\nIMPROVEMENTS:\n* Update documentation for installing tools.\n  [[GH-3413]](https://github.com/fatih/vim-go/pull/3413)\n* Show diagnostics via go#tool#DescribeBalloon().\n  [[GH-3415]](https://github.com/fatih/vim-go/pull/3415)\n  [[GH-3417]](https://github.com/fatih/vim-go/pull/3417)\n* Allow version of individual tools to be installed with `:GoUpdateBinaries`\n  and `:GoInstallBinaries` to be overridden by users.\n  [[GH-3435]](https://github.com/fatih/vim-go/pull/3435)\n  [[GH-3436]](https://github.com/fatih/vim-go/pull/3436)\n* Highlight numeric formats introduced in Go 1.13.\n  [[GH-3440]](https://github.com/fatih/vim-go/pull/3440)\n\nBUG FIXES:\n* Fix quoting of arguments when shell is set to pwsh on Windows.\n  [[GH-3422]](https://github.com/fatih/vim-go/pull/3422)\n* Use -mod=mod instead of -mod=readonly when installing tools.\n  [[GH-3449]](https://github.com/fatih/vim-go/pull/3449)\n* Remove support for /* */ comments in go.mod files.\n  [[GH-3460]](https://github.com/fatih/vim-go/pull/3460)\n* Fix go.work syntax support.\n  [[GH-3461]](https://github.com/fatih/vim-go/pull/3461)\n* Split the buffer without considering the current buffer when a mapping to\n  split and jump to definition is used.\n  [[GH-3462]](https://github.com/fatih/vim-go/pull/3462)\n* Fix hilighting of package references via `:GoSameIds`.\n  [[GH-3469]](https://github.com/fatih/vim-go/pull/3469)\n\n## v1.26 - (April 23, 2022)\n\nBACKWARDS INCOMPATIBILITIES:\n\nIMPROVEMENTS:\n* Add mapping for formatting, `(go-fmt)`.\n  [[GH-3209]](https://github.com/fatih/vim-go/pull/3209)\n* Add `tr` snippet for `\"testing.T\".Run`.\n  [[GH-3210]](https://github.com/fatih/vim-go/pull/3210)\n  [[GH-3220]](https://github.com/fatih/vim-go/pull/3220)\n* Use `go env GOBIN` to determine `GOBIN`'s value.\n  [[GH-3207]](https://github.com/fatih/vim-go/pull/3207)\n* List register in the debugger.\n  [[GH-3221]](https://github.com/fatih/vim-go/pull/3221)\n* Install the latest release of tools that seem to be using tags to do releases\n  instead of installing from their master/main branch.\n  [[GH-3227]](https://github.com/fatih/vim-go/pull/3227)\n* Expose error message when `gopls` cannot be found and\n  `g:go_echo_command_info` is set.\n  [[GH-3244]](https://github.com/fatih/vim-go/pull/3244)\n* Install all tools in module aware mode in preparation for Go 1.17 release.\n  [[GH-3226]](https://github.com/fatih/vim-go/pull/3226)\n* Add `g:go_doc_balloon` to allow godoc to be displayed in hover balloons.\n  [[GH-3252]](https://github.com/fatih/vim-go/pull/3252)\n* Default to using `revive` in place of `golint`.\n  [[GH-3248]](https://github.com/fatih/vim-go/pull/3248)\n  [[GH-3401]](https://github.com/fatih/vim-go/pull/3401)\n* Teach `:GoDebugPrint` to show function call return values.\n  [[GH-3256]](https://github.com/fatih/vim-go/pull/3256)\n* Do not enable keyify unless in GOPATH.\n  [[GH-3095]](https://github.com/fatih/vim-go/pull/3095)\n* Show LSP messages to users.\n  [[GH-3058]](https://github.com/fatih/vim-go/pull/3058)\n* Check omnifunc's value before executing actions on CompletedDone event.\n  [[GH-3274]](https://github.com/fatih/vim-go/pull/3274)\n* Highlight new form of build constraints.\n  [[GH-3292]](https://github.com/fatih/vim-go/pull/3292)\n* Teach `:GoDiagnostics` to handle package pattern arguments.\n  [[GH-3297]](https://github.com/fatih/vim-go/pull/3297)\n* Add `g:go_debug_subsitute_paths` to support debugging applications when the\n  source is hosted in a local location that is different from where the binary\n  was compiled.\n  [[GH-3301]](https://github.com/fatih/vim-go/pull/3301)\n* Wrap text in the fzf preview window by default.\n  [[GH-3310]](https://github.com/fatih/vim-go/pull/3310)\n* Wait for up to five seconds when opening a connection to a remote debugger.\n  [[GH-3312]](https://github.com/fatih/vim-go/pull/3312)\n* Install tools with `go install` instead of `go get`.\n  [[GH-3317]](https://github.com/fatih/vim-go/pull/3317)\n  [[GH-3370]](https://github.com/fatih/vim-go/pull/3370)\n* Update `:GoPlay` to use `go.dev/play` instead of `play.golang.org`.\n  [[GH-3331]](https://github.com/fatih/vim-go/pull/3331)\n  [[GH-3348]](https://github.com/fatih/vim-go/pull/3348)\n* Recurse local variables more deeply when debugging.\n  [[GH-3344]](https://github.com/fatih/vim-go/pull/3344)\n* Add syntax elements for `any` and `comparable` types.\n  [[GH-3351]](https://github.com/fatih/vim-go/pull/3351)\n* Add syntax support for go.work files.\n  [[GH-3375]](https://github.com/fatih/vim-go/pull/3375)\n* Show the current goroutine at the top of the list of goroutines when debugging.\n  [[GH-3379]](https://github.com/fatih/vim-go/pull/3379)\n* Add `:GoModReload` and autocmd events to reload go.mod when it changes on\n  disk and is open in a buffer.\n  [[GH-3387]](https://github.com/fatih/vim-go/pull/3387)\n  [[GH-3391]](https://github.com/fatih/vim-go/pull/3391)\n* Add syntax support for generics.\n  [[GH-3397]](https://github.com/fatih/vim-go/pull/3397)\n* Remove invalid numeric literal highlighting.\n  [[GH-3404]](https://github.com/fatih/vim-go/pull/3404)\n\nBUG FIXES:\n* Handle terminating parenthesis on hexadecimal values.\n  [[GH-3216]](https://github.com/fatih/vim-go/pull/3216)\n* Fix applying text edits from gopls.\n  [[GH-3231]](https://github.com/fatih/vim-go/pull/3231)\n* Apply arguments to `:GoCoverageBrowser`.\n  [[GH-3240]](https://github.com/fatih/vim-go/pull/3240)\n* Fix `:GoFillStruct` when `g:go_fillstruct_mode` is `gopls`.\n  [[GH-3279]](https://github.com/fatih/vim-go/pull/3279)\n* Fix example in `g:go_metalinter_enabled` documentation.\n  [[GH-3291]](https://github.com/fatih/vim-go/pull/3291)\n* Fix changing directories in older Vims.\n  [[GH-3299]](https://github.com/fatih/vim-go/pull/3299)\n* Highlight the receive type when method declarations that omit the receiver\n  identifier.\n  [[GH-3306]](https://github.com/fatih/vim-go/pull/3306)\n* Do not highlight misspellings in import paths.\n  [[GH-3308]](https://github.com/fatih/vim-go/pull/3308)\n  [[GH-3321]](https://github.com/fatih/vim-go/pull/3321)\n* Handle shell quoting when execing.\n  [[GH-3323]](https://github.com/fatih/vim-go/pull/3323)\n* Do not automatically add directories from the module cache into the LSP\n  workspace.\n  [[GH-3343]](https://github.com/fatih/vim-go/pull/3343)\n* Resolve symlinks in autocmd events.\n  [[GH-3353]](https://github.com/fatih/vim-go/pull/3353)\n* Fix `:GoRename` in Neovim so that it does not take 10 seconds to complete.\n  [[GH-3386]](https://github.com/fatih/vim-go/pull/3386)\n* Fix `:GoDebugConnect` argument handling.\n  [[GH-3400]](https://github.com/fatih/vim-go/pull/3400)\n\n## v1.25 - (April 18, 2021)\n\nBACKWARDS INCOMPATIBILITIES:\n* Remove g:go_autodetect_gopath.\n  [[GH-3078]](https://github.com/fatih/vim-go/pull/3078)\n\nIMPROVEMENTS:\n* Clarify allowed values for `gopls` related configuration options.\n  [[GH-3016]](https://github.com/fatih/vim-go/pull/3016)\n  [[GH-3017]](https://github.com/fatih/vim-go/pull/3017)\n* Add `g:go_fillstruct_mode` to allow `:GoFillStruct` to be satisfied by either\n  `fillstruct` or by `gopls`.\n  [[GH-3018]](https://github.com/fatih/vim-go/pull/3018)\n* Add `:GoDebugTestFunc` to debug the test function surrounding the current\n  cursor location.\n  [[GH-3011]](https://github.com/fatih/vim-go/pull/3011)\n* Implicitly add a workspace when a file from a module is opened.\n  [[GH-3028]](https://github.com/fatih/vim-go/pull/3028)\n* Add support for using static check as the gometalinter.\n  [[GH-3036]](https://github.com/fatih/vim-go/pull/3036)\n  [[GH-3133]](https://github.com/fatih/vim-go/pull/3133)\n* Add `g:go_debug_mappings` to allow the debug key mappings to be customized.\n  [[GH-3035]](https://github.com/fatih/vim-go/pull/3035)\n  [[GH-3143]](https://github.com/fatih/vim-go/pull/3143)\n* Use `gopls` as the default instead of `guru` to satisfy `:GoImplements`.\n  [[GH-3034]](https://github.com/fatih/vim-go/pull/3034)\n* Deprecate g:go_diagnostics_enabled` and add `g:go_diagnostics_level` to allow\n  more finely grained control of the handling of diagnostics messages.\n  [[GH-3050]](https://github.com/fatih/vim-go/pull/3050)\n  [[GH-3052]](https://github.com/fatih/vim-go/pull/3052)\n  [[GH-3119]](https://github.com/fatih/vim-go/pull/3119)\n* Add support for allowing `g:go_gopls_local`  to specify different local\n  imports values per workspace.\n  [[GH-3053]](https://github.com/fatih/vim-go/pull/3053)\n* Improve `:GoDecls` and `:GoDeclsDir` display.\n  [[GH-3081]](https://github.com/fatih/vim-go/pull/3081)\n* Preserve existing window layout when debugging and `g:go_debug_windows` is\n  empty.\n  [[GH-3068]](https://github.com/fatih/vim-go/pull/3068)\n* Show identifier in fzf's preview window with `:GoDecls` and `:GoDeclsDir`.\n  [[GH-3083]](https://github.com/fatih/vim-go/pull/3083)\n* Use `gopls` for `:GoCallers`.\n  [[GH-3088]](https://github.com/fatih/vim-go/pull/3088)\n  [[GH-3090]](https://github.com/fatih/vim-go/pull/3090)\n  [[GH-3141]](https://github.com/fatih/vim-go/pull/3141)\n  [[GH-3142]](https://github.com/fatih/vim-go/pull/3142)\n* Update denite integration to work with python3.9.\n  [[GH-3097]](https://github.com/fatih/vim-go/pull/3097)\n* Add syntax highlighting for go.sum files.\n  [[GH-3102]](https://github.com/fatih/vim-go/pull/3102)\n* Change the default from metalinter to staticcheck.\n  [[GH-3126]](https://github.com/fatih/vim-go/pull/3126)\n* Add `g:go_debug_preserve_layout` to prevent `:GoDebug` and friends from\n  closing windows.\n  [[GH-3125]](https://github.com/fatih/vim-go/pull/3125)\n* Add support for `fillstruct`'s new `-tags` flag.\n  [[GH-3156]](https://github.com/fatih/vim-go/pull/3156)\n* Display map key and slice elements more usefully in the local vars window in\n  debug mode.\n  [[GH-3170]](https://github.com/fatih/vim-go/pull/3170)\n* Add support for go.mod's `retract` directive.\n  [[GH-3166]](https://github.com/fatih/vim-go/pull/3166)\n* Do not execute disabled code actions.\n  [[GH-3155]](https://github.com/fatih/vim-go/pull/3155)\n* Add `:GoDebugConnect` to support connecting to an instance of delve started\n  outside of vim-go.\n  [[GH-3179]](https://github.com/fatih/vim-go/pull/3179)\n* Use gopls to adjust imports and formatting by default.\n  [[GH-2986]](https://github.com/fatih/vim-go/pull/2986)\n* Set the filetype for .tmpl files to gohtmltmpl even if it's already been set.\n  [[GH-3146]](https://github.com/fatih/vim-go/pull/3146)\n\nBUG FIXES:\n* Remove implications that terminal mode is only applied for Neovim.\n  [[GH-3010]](https://github.com/fatih/vim-go/pull/3010)\n* Correct documentation to clearly show the default value for\n  `g:go_gopls_options`.\n  [[GH-3019]](https://github.com/fatih/vim-go/pull/3019)\n* Allow truthy values for `g:go_gopls_gofumpt`.\n  [[GH-3017]](https://github.com/fatih/vim-go/pull/3017)\n  [[GH-3022]](https://github.com/fatih/vim-go/pull/3022)\n* Fix quickfix title for `:GoMetaLinter`.\n  [[GH-3040]](https://github.com/fatih/vim-go/pull/3040)\n* Change key mapping for (go-debug-halt) to F8 to resolve collision with key\n  mapping for (go-debug-print).\n  [[GH-3047]](https://github.com/fatih/vim-go/pull/3047)\n* Handle gopls v0.5.2 addition of a prefix on the expected code actions names.\n  [[GH-3077]](https://github.com/fatih/vim-go/pull/3077)\n* Make sure all buffers' mappings are restored when debugging stops.\n  [[GH-3048]](https://github.com/fatih/vim-go/pull/3048)\n* Return early when `g:go_referrers_modes` is `gopls` and `gopls` is disabled.\n  [[GH-3090]](https://github.com/fatih/vim-go/pull/3090)\n* Handle yet another error format produced by golangci-lint.\n  [[GH-3094]](https://github.com/fatih/vim-go/pull/3094)\n* Handle additional ways that gopls can provide links for godoc.\n  [[GH-3112]](https://github.com/fatih/vim-go/pull/3112)\n* Remove implication that `g:go_def_reuse_buffer` only applies to split variant\n  of jumping to a definition.\n  [[GH-3128]](https://github.com/fatih/vim-go/pull/3128)\n* Organize imports correctly when `gopls` formatting uses `gofumpt`.\n  [[GH-3154]](https://github.com/fatih/vim-go/pull/3154)\n* Rename all instances of an identifier when `g:go_rename_mode` is `gopls`.\n  [[GH-3181]](https://github.com/fatih/vim-go/pull/3181)\n  [[GH-3182]](https://github.com/fatih/vim-go/pull/3182)\n* Terminate a case statement in the select snippet with a colon.\n  [[GH-3185]](https://github.com/fatih/vim-go/pull/3185)\n* Fix syntax highlighting in template files.\n  [[GH-3188]](https://github.com/fatih/vim-go/pull/3188)\n  [[GH-3189]](https://github.com/fatih/vim-go/pull/3189)\n\n## v1.24 - (September 15, 2020)\n\nIMPROVEMENTS:\n* Clarify how `g:go_imports_autosave` and `g:go_fmt_autosave` interact.\n  [[GH-2893]](https://github.com/fatih/vim-go/pull/2893)\n* Document what the working directory will be for `:GoRun`.\n  [[GH-2898]](https://github.com/fatih/vim-go/pull/2898)\n* Add Ultisnip snippet for wrapping errors.\n  [[GH-2883]](https://github.com/fatih/vim-go/pull/2883)\n* Beautify the godoc pop up window border.\n  [[GH-2900]](https://github.com/fatih/vim-go/pull/2900)\n* Default `g:go_doc_url` to https://pkg.go.dev.\n  [[GH-2884]](https://github.com/fatih/vim-go/pull/2884)\n* Default `g:go_gopls_options` to `[-remote=auto]` to share gopls instances\n  with other plugins and multiple instances of Vim.\n  [[GH-2905]](https://github.com/fatih/vim-go/pull/2905)\n* Use the module root as the working directory when renaming so that all\n  references to the symbol will be renamed when in module aware mode and\n  `g:go_rename_command` is set to `gopls`.\n  [[GH-2917]](https://github.com/fatih/vim-go/pull/2917)\n* Change `g:go_rename_command`'s default to `gopls`.\n  [[GH-2922]](https://github.com/fatih/vim-go/pull/2922)\n* Do not send unnecessary textDocument/didChange notifications to `gopls`.\n  [[GH-2902]](https://github.com/fatih/vim-go/pull/2902)\n  [[GH-2930]](https://github.com/fatih/vim-go/pull/2930)\n* Stop the debugger when the process being debugged exits.\n  [[GH-2921]](https://github.com/fatih/vim-go/pull/2921)\n* Use the module package cache as a source of packages candidates when trying\n  to complete package names.\n  [[GH-2936]](https://github.com/fatih/vim-go/pull/2936)\n  [[GH-2939]](https://github.com/fatih/vim-go/pull/2939)\n* Allow interaction with Vim while waiting for a breakpoint to be hit while\n  debugging.\n  [[GH-2932]](https://github.com/fatih/vim-go/pull/2932)\n* Refactor Vim signs used for debugging breakpoints to avoid id collision with\n  other plugins.\n  [[GH-2943]](https://github.com/fatih/vim-go/pull/2943)\n* Refactor debugger's rpc response handling to be asynchronous so that Vim will\n  be responsive while the program being debugged is executing.\n  [[GH-2948]](https://github.com/fatih/vim-go/pull/2948)\n  [[GH-2952]](https://github.com/fatih/vim-go/pull/2952)\n* Warn when the debugger breaks in a file that has changed since debugging started.\n  [[GH-2950]](https://github.com/fatih/vim-go/pull/2950)\n* Enable `go-run` mappings that use the terminal to work with Vim in addition to Neovim.\n  [[GH-2956]](https://github.com/fatih/vim-go/pull/2956)\n* Use existing diagnostics for the file when the file hasn't changed and\n  `g:go_metalinter_command` is `gopls`.\n  [[GH-2960]](https://github.com/fatih/vim-go/pull/2960)\n* Add a new option, `g:go_code_completion_icase`, to allow ignoring case when\n  filtering completion results.\n  [[GH-2961]](https://github.com/fatih/vim-go/pull/2961)\n * Make sure tools are not cross-compiled with `:GoInstallBinaries` and\n   `:GoUpdateBinaries`.\n   [[GH-2982]](https://github.com/fatih/vim-go/pull/2982)\n   [[GH-2988]](https://github.com/fatih/vim-go/pull/2988)\n* Add `:GoDebugHalt` to allow a program being debugged to be paused before it\n  hits a breakpoint.\n  [[GH-2983]](https://github.com/fatih/vim-go/pull/2983)\n* Clear highlighting of the current line when after resuming when debugging.\n  [[GH-2984]](https://github.com/fatih/vim-go/pull/2984)\n* Add `:GoDebugAttach` to debug a running process.\n  [[GH-2989]](https://github.com/fatih/vim-go/pull/2989)\n* Add `g:go_term_reuse` option to allow the reuse of a terminal window.\n  [[GH-2990]](https://github.com/fatih/vim-go/pull/2990)\n* Add official support for using `gopls`' `gofumpt` workspace setting via\n  `g:go_gopls_gofumpt`.\n  [[GH-2994]](https://github.com/fatih/vim-go/pull/2994)\n  [[GH-3005]](https://github.com/fatih/vim-go/pull/3005)\n* Add support for using `gopls`' workspace settings that are otherwise not yet\n  officially supported by vim-go.\n  [[GH-2994]](https://github.com/fatih/vim-go/pull/2994)\n\nBUG FIXES:\n* Fix call to non-existent function in terminal mode edge case.\n  [[GH-2895]](https://github.com/fatih/vim-go/pull/2895)\n* Do not show errors when adding a text property for highlighting fails.\n  [[GH-2892]](https://github.com/fatih/vim-go/pull/2892)\n* Include `errcheck` in `g:go_metalinter_enabled`'s default.\n  [[GH-2903]](https://github.com/fatih/vim-go/pull/2903)\n* Fix display of completion selection information on command-line when\n  `g:go_echo_go_info` is enabled.\n  [[GH-2907]](https://github.com/fatih/vim-go/pull/2907)\n* Prevent `:GoDebugBreakpoint` from causing delve to exit.\n  [[GH-2908]](https://github.com/fatih/vim-go/pull/2908)\n* Use the resolved directory name for `gopls`' working directory when `go.mod`\n  is in a symlinked path.\n  [[GH-2913]](https://github.com/fatih/vim-go/pull/2913)\n* Fix buffer reuse with `:GoDef`.\n  [[GH-2928]](https://github.com/fatih/vim-go/pull/2928)\n* Handle breakpoints that are already set before calling `:GoDebugStart` or\n  `:GoDebugTest` in some locales that cause the `sign place` output to vary.\n  [[GH-2921]](https://github.com/fatih/vim-go/pull/2921)\n* Handle diagnostic errors at the end of a .go file.\n  [[GH-2942]](https://github.com/fatih/vim-go/pull/2942)\n* Fix the `go-implements` mapping to use respect `g:go_implements_mode`.\n  [[GH-2944]](https://github.com/fatih/vim-go/pull/2944)\n* Handle null results from `gopls` when getting definitions or type definitions\n  from virtual files.\n  [[GH-2951]](https://github.com/fatih/vim-go/pull/2951)\n* Fix warning when Neovim is older than v0.4.0.\n  [[GH-2959]](https://github.com/fatih/vim-go/pull/2959)\n* Correct documentation that referred to `g:go_imports_command` to refer to\n  `g:go_imports_mode`  instead.\n  [[GH-2969]](https://github.com/fatih/vim-go/pull/2969)\n* Remove reference to gocode in error message when `g:go_info_mode` is set to\n  an unsupported value.\n  [[GH-2978]](https://github.com/fatih/vim-go/pull/2978)\n* Make sure debugging commands are configured when debugging a second time\n  within a single Vim session.\n  [[GH-2985]](https://github.com/fatih/vim-go/pull/2985)\n* Correct documentation in for `:GoModifyTags` when adding a specific tag\n  value.\n  [[GH-3001]](https://github.com/fatih/vim-go/pull/3001)\n* Fix the path given to `gopls` when `let g:go_metalinter='gopls'` and\n  `:GoMetaLinter` is called without any arguments.\n  [[GH-2992]](https://github.com/fatih/vim-go/pull/2992)\n* Do not override a user's configuration for `GoDebugBreakpoint` or\n  `GoDebugCurrent` highlight groups.\n  [[GH-2998]](https://github.com/fatih/vim-go/pull/2998)\n* Apply `gopls` text edits correctly that insert solitary newlines.\n  [[GH-3000]](https://github.com/fatih/vim-go/pull/3000)\n\n## v1.23 - (May 16, 2020)\n\nBACKWARDS INCOMPATIBILITIES:\n* Remove support for gocode.\n  [[GH-2686]](https://github.com/fatih/vim-go/pull/2686)\n* Require at least Neovim >= 0.4.0\n  [[GH-2853]](https://github.com/fatih/vim-go/pull/2853)\n  [[GH-2856]](https://github.com/fatih/vim-go/pull/2856)\n  [[GH-2863]](https://github.com/fatih/vim-go/pull/2863)\n\nIMPROVEMENTS:\n* Make signs for breakpoints configurable.\n  [[GH-2676]](https://github.com/fatih/vim-go/pull/2676)\n  [[GH-2690]](https://github.com/fatih/vim-go/pull/2690)\n* Enable g:go_gopls_complete_unimported by default to stay aligned with gopls' defaults.\n  [[GH-2695]](https://github.com/fatih/vim-go/pull/2695)\n* Document mappings that were recently added.\n  [[GH-2699]](https://github.com/fatih/vim-go/pull/2699)\n* Handle null arrays better in gopls responses.\n  [[GH-2703]](https://github.com/fatih/vim-go/pull/2703)\n* Use `gopls` defaults by default when they're not otherwise specified in vim-go options.\n  [[GH-2696]](https://github.com/fatih/vim-go/pull/2696)\n* Add support for `gomodifytags --skip-unexported`\n  [[GH-2660]](https://github.com/fatih/vim-go/pull/2660)\n* Show problems that prevent golangci-lint from running linters.\n  [[GH-2706]](https://github.com/fatih/vim-go/pull/2706)\n  [[GH-2720]](https://github.com/fatih/vim-go/pull/2720)\n* Support golangci-lint config file by not using `--disable-all` when\n  `g:go_metalinter_enable` or `g:go_metalinter_autosave_enabled` is set to an\n  empty array.\n  [[GH-2655]](https://github.com/fatih/vim-go/pull/2655)\n  [[GH-2715]](https://github.com/fatih/vim-go/pull/2715)\n* Add support for Vim8 terminals.\n  [[GH-2639]](https://github.com/fatih/vim-go/pull/2639)\n  [[GH-2736]](https://github.com/fatih/vim-go/pull/2736)\n* Replace `g:go_gopls_fuzzy_matching` with `g:go_gopls_matcher` in response to\n  `gopls` deprecation of its `fuzzyMatching` option.\n  [[GH-2728]](https://github.com/fatih/vim-go/pull/2728)\n* Set statuses and progress messages consistently for code quality tools.\n  [[GH-2727]](https://github.com/fatih/vim-go/pull/2727)\n* Add a new supported value to `g:go_fmt_command` to format with `gopls`.\n  [[GH-2729]](https://github.com/fatih/vim-go/pull/2729)\n  [[GH-2752]](https://github.com/fatih/vim-go/pull/2752)\n  [[GH-2852]](https://github.com/fatih/vim-go/pull/2852)\n* Handle changes to `go test -v` output.\n  [[GH-2743]](https://github.com/fatih/vim-go/pull/2743)\n* Add `g:go_gopls_mod_tempfile` to configure `gopls`' `tempModfile`\n  configuration.\n  [[GH-2747]](https://github.com/fatih/vim-go/pull/2747)\n* Add `g:go_gopls_options` to configure `gopls`' commandline options.\n  [[GH-2747]](https://github.com/fatih/vim-go/pull/2747)\n* Improve readability of gopls logs.\n  [[GH-2773]](https://github.com/fatih/vim-go/pull/2773)\n* Introduce `g:go_implements_mode` to allow `:GoImplements` to be satisfied\n  with `gopls`.\n  [[GH-2741]](https://github.com/fatih/vim-go/pull/2741)\n  [[GH-2799]](https://github.com/fatih/vim-go/pull/2799)\n* Introduce `g:go_imports_mode` to allow `:GoImports` to be satisfied with\n  `gopls`.\n  [[GH-2791]](https://github.com/fatih/vim-go/pull/2791)\n  [[GH-2794]](https://github.com/fatih/vim-go/pull/2794)\n  [[GH-2796]](https://github.com/fatih/vim-go/pull/2796)\n  [[GH-2848]](https://github.com/fatih/vim-go/pull/2848)\n* Send LSP synchronization messages to `gopls` when the file does not yet exist\n  on disk as long as its directory exists.\n  [[GH-2805]](https://github.com/fatih/vim-go/pull/2805)\n* Run `gogetdoc` in the buffer's directory so that it will work regardless of\n  the user's working directory in module-aware mode.\n  [[GH-2804]](https://github.com/fatih/vim-go/pull/2804)\n* Add `g:go_gopls_analyses` to support `gopls`' analyses options.\n  [[GH-2820]](https://github.com/fatih/vim-go/pull/2820)\n* Add `g:go_gopls_local` to support `gopls`' local option to control how third\n  party imports are organized.\n  [[GH-2821]](https://github.com/fatih/vim-go/pull/2821)\n* Use gopls to get documentation and documentation links for identifiers under\n  the cursor.\n  [[GH-2822]](https://github.com/fatih/vim-go/pull/2822)\n  [[GH-2839]](https://github.com/fatih/vim-go/pull/2839)\n* Clarify documentation for terminal options.\n  [[GH-2843]](https://github.com/fatih/vim-go/pull/2843)\n\nBUG FIXES:\n* Use the discovered full path for gopls when renaming.\n  [[GH-2692]](https://github.com/fatih/vim-go/pull/2692)\n* Execute commands correctly on windows when `'shell'` is not cmd.exe\n  [[GH-2713]](https://github.com/fatih/vim-go/pull/2713)\n  [[GH-2724]](https://github.com/fatih/vim-go/pull/2724)\n* Always execute `errcheck` in the current package's directory.\n  [[GH-2726]](https://github.com/fatih/vim-go/pull/2726)\n* Fix errors when highlighting diagnostics after a `:GoImports`.\n  [[GH-2746]](https://github.com/fatih/vim-go/pull/2746)\n* Preserve errors from formatting when both formatting and metalinting happen\n  on save.\n  [[GH-2733]](https://github.com/fatih/vim-go/pull/2733)\n  [[GH-2810]](https://github.com/fatih/vim-go/pull/2810)\n* Preserve ordering of gopls messages in the log.\n  [[GH-2753]](https://github.com/fatih/vim-go/pull/2753)\n* Fix `:GoDef` on windows when `g:go_def_mode` is set to `gopls`.\n  [[GH-2768]](https://github.com/fatih/vim-go/pull/2768)\n* Handle null values from `gopls`.\n  [[GH-2778]](https://github.com/fatih/vim-go/pull/2778)\n* Preserve diagnostics highlights after formatting.\n  [[GH-2779]](https://github.com/fatih/vim-go/pull/2779)\n* Fix the decoding and encoding of multi-byte file paths received from and sent\n  to `gopls`.\n  [[GH-2784]](https://github.com/fatih/vim-go/pull/2784)\n* Fix `:GoRun` so that it works as expected when the current working directory\n  is neither in GOPATH nor within a module.\n  [[GH-2782]](https://github.com/fatih/vim-go/pull/2782)\n  [[GH-2818]](https://github.com/fatih/vim-go/pull/2818)\n  [[GH-2842]](https://github.com/fatih/vim-go/pull/2842)\n* Use absolute file paths for `:GoRun`'s arguments in terminal mode.\n  [[GH-2844]](https://github.com/fatih/vim-go/pull/2844)\n* Show the command executed by `:GoRun` when `g:go_debug` includes `'shell-commands'`.\n  [[GH-2785]](https://github.com/fatih/vim-go/pull/2785)\n  [[GH-2817]](https://github.com/fatih/vim-go/pull/2817)\n* Clear the list for formatting errors when `g:go_fmt_command` is `gopls`.\n  [[GH-2790]](https://github.com/fatih/vim-go/pull/2790)\n* Handle text edits from gopls that are only line insertions.\n  [[GH-2802]](https://github.com/fatih/vim-go/pull/2802)\n  [[GH-2803]](https://github.com/fatih/vim-go/pull/2803)\n* Add `g:go_imports_autosave` so that imports can be adjusted on save when\n  `g:go_imports_mode` is set to `gopls`.\n  [[GH-2800]](https://github.com/fatih/vim-go/pull/2800)\n  [[GH-2858]](https://github.com/fatih/vim-go/pull/2858)\n* Correct vim-go's help to correctly identify `g:go_referrer_mode`'s default.\n  [[GH-2832]](https://github.com/fatih/vim-go/pull/2832)\n* Clear the quickfix list when `:GoLint` succeeds.\n  [[GH-2833]](https://github.com/fatih/vim-go/pull/2833)\n* Respect arguments to `:GoDocBrowser`.\n  [[GH-2822]](https://github.com/fatih/vim-go/pull/2822)\n* Use the correct path to documentation for struct fields with `:GoDocBrowser`.\n  [[GH-2822]](https://github.com/fatih/vim-go/pull/2822)\n* Do not try parsing errors from terminal jobs when the working directory has\n  been removed.\n  [[GH-2824]](https://github.com/fatih/vim-go/pull/2824)\n* Document that `g:go_jump_to_error` apples to running the metalinter on save,\n  too.\n  [[GH-2854]](https://github.com/fatih/vim-go/pull/2854)\n* Ignore commented out import statements when executing `:GoImport`.\n  [[GH-2862]](https://github.com/fatih/vim-go/pull/2862)\n* Interpret file paths in `go vet` errors relative to the current buffer's\n  directory.\n  [[GH-2882]](https://github.com/fatih/vim-go/pull/2882)\n\n## v1.22 - (January 30, 2020)\n\nBACKWARDS INCOMPATIBILITIES:\n* Drop support for Vim 7.4. The minimum required version of Vim is now 8.0.1453.\n  [[GH-2495]](https://github.com/fatih/vim-go/pull/2495)\n  [[GH-2497]](https://github.com/fatih/vim-go/pull/2497)\n* Drop support for `gometalinter`\n  [[GH-2494]](https://github.com/fatih/vim-go/pull/2494)\n\nIMPROVEMENTS:\n* Highlight the `go` keyword in go.mod files.\n  [[GH-2473]](https://github.com/fatih/vim-go/pull/2473)\n* Use echo functions consistently.\n  [[GH-2458]](https://github.com/fatih/vim-go/pull/2458)\n* Add support for managing goroutines in debugger.\n  [[GH-2463]](https://github.com/fatih/vim-go/pull/2463)\n  [[GH-2527]](https://github.com/fatih/vim-go/pull/2527)\n* Document `g:go_doc_popup_window`.\n  [[GH-2506]](https://github.com/fatih/vim-go/pull/2506)\n* Make `g:go_doc_popup_window=1` work for Neovim, too.\n  [[GH-2451]](https://github.com/fatih/vim-go/pull/2451)\n  [[GH-2512]](https://github.com/fatih/vim-go/pull/2512)\n* Handle errors jumping to a definition in a file open in another Vim process\n  better.\n  [[GH-2518]](https://github.com/fatih/vim-go/pull/2518)\n* Improve the UX when the gopls binary is missing.\n  [[GH-2522]](https://github.com/fatih/vim-go/pull/2522)\n* Use gopls instead of guru for `:GoSameIds`.\n  [[GH-2519]](https://github.com/fatih/vim-go/pull/2519)\n* Use gopls instead of guru for `:GoReferrers`.\n  [[GH-2535]](https://github.com/fatih/vim-go/pull/2535)\n* Update documentation for `g:go_addtags_transform`.\n  [[GH-2541]](https://github.com/fatih/vim-go/pull/2541)\n* Install most helper tools in module aware mode.\n  [[GH-2545]](https://github.com/fatih/vim-go/pull/2545)\n* Add a new option, `g:go_referrers_mode` to allow the user to choose whether\n  to use gopls or guru for finding references.\n  [[GH-2566]](https://github.com/fatih/vim-go/pull/2566)\n* Add options to control how gopls responds to completion requests.\n  [[GH-2567]](https://github.com/fatih/vim-go/pull/2567)\n  [[GH-2568]](https://github.com/fatih/vim-go/pull/2568)\n* Add syntax highlighting for binary literals.\n  [[GH-2557]](https://github.com/fatih/vim-go/pull/2557)\n* Improve highlighting of invalid numeric literals.\n  [[GH-2571]](https://github.com/fatih/vim-go/pull/2571)\n  [[GH-2587]](https://github.com/fatih/vim-go/pull/2587)\n  [[GH-2589]](https://github.com/fatih/vim-go/pull/2589)\n  [[GH-2584]](https://github.com/fatih/vim-go/pull/2584)\n  [[GH-2597]](https://github.com/fatih/vim-go/pull/2597)\n  [[GH-2599]](https://github.com/fatih/vim-go/pull/2599)\n* Add highlighting of sections reported by gopls diagnostics' errors\n  and warnings.\n  [[GH-2569]](https://github.com/fatih/vim-go/pull/2569)\n  [[GH-2643]](https://github.com/fatih/vim-go/pull/2643)\n* Make the highlighting of fzf decls configurable.\n  [[GH-2572]](https://github.com/fatih/vim-go/pull/2572)\n  [[GH-2579]](https://github.com/fatih/vim-go/pull/2579)\n* Support renaming with gopls.\n  [[GH-2577]](https://github.com/fatih/vim-go/pull/2577)\n  [[GH-2618]](https://github.com/fatih/vim-go/pull/2618)\n* Add an option, `g:go_gopls_enabled`, to allow gopls integration to be\n  disabled.\n  [[GH-2605]](https://github.com/fatih/vim-go/pull/2605)\n  [[GH-2609]](https://github.com/fatih/vim-go/pull/2609)\n  [[GH-2638]](https://github.com/fatih/vim-go/pull/2638)\n  [[GH-2640]](https://github.com/fatih/vim-go/pull/2640)\n* Add a buffer level option, `b:go_fmt_options`, to control formatting options\n  per buffer.\n  [[GH-2613]](https://github.com/fatih/vim-go/pull/2613)\n* Use build tags when running `:GoVet`.\n  [[GH-2615]](https://github.com/fatih/vim-go/pull/2615)\n* Add new snippets for UltiSnips.\n  [[GH-2623]](https://github.com/fatih/vim-go/pull/2623)\n  [[GH-2627]](https://github.com/fatih/vim-go/pull/2627)\n* Expand completions as snippets when `g:go_gopls_use_placeholders` is set.\n  [[GH-2624]](https://github.com/fatih/vim-go/pull/2624)\n* Add a new function, `:GoDiagnostics` and an associated mapping for seeing\n  `gopls` diagnostics. Because of the performance implications on large\n  projects, `g:go_diagnostics_enabled` controls whether all diagnostics are\n  processed or only the diagnostics for the current buffer.\n  [[GH-2612]](https://github.com/fatih/vim-go/pull/2612)\n* Explain how to find and detect multiple copies of vim-go in the FAQ.\n  [[GH-2632]](https://github.com/fatih/vim-go/pull/2632)\n* Update the issue template to ask for the gopls version and\n  `:GoReportGitHubIssue` to provide it.\n  [[GH-2630]](https://github.com/fatih/vim-go/pull/2630)\n* Use text properties when possible for some highlighting cases.\n  [[GH-2652]](https://github.com/fatih/vim-go/pull/2652)\n  [[GH-2662]](https://github.com/fatih/vim-go/pull/2662)\n  [[GH-2663]](https://github.com/fatih/vim-go/pull/2663)\n  [[GH-2672]](https://github.com/fatih/vim-go/pull/2672)\n  [[GH-2678]](https://github.com/fatih/vim-go/pull/2678)\n\n\nBUG FIXES:\n* Fix removal of missing directories from gopls workspaces.\n  [[GH-2507]](https://github.com/fatih/vim-go/pull/2507)\n* Change to original window before trying to change directories when term job\n  ends.\n  [[GH-2508]](https://github.com/fatih/vim-go/pull/2508)\n* Swallow errors when the hover info cannot be determined.\n  [[GH-2515]](https://github.com/fatih/vim-go/pull/2515)\n* Fix errors when trying to debug lsp and hover.\n  [[GH-2516]](https://github.com/fatih/vim-go/pull/2516)\n* Reset environment variables on Vim <= 8.0.1831 .\n  [[GH-2523]](https://github.com/fatih/vim-go/pull/2523)\n* Handle empty results from delve.\n  [[GH-2526]](https://github.com/fatih/vim-go/pull/2526)\n* Do not overwrite `updatetime` when `g:go_auto_sameids` or\n  `g:go_auto_type_info` is set.\n  [[GH-2529]](https://github.com/fatih/vim-go/pull/2529)\n* Fix example for `g:go_debug_log_output` in docs.\n  [[GH-2547]](https://github.com/fatih/vim-go/pull/2547)\n* Use FileChangedShellPost instead of FileChangedShell so that reload messages\n  are not hidden.\n  [[GH-2549]](https://github.com/fatih/vim-go/pull/2549)\n* Restore cwd after `:GoTest` when `g:go_term_enabled` is set.\n  [[GH-2556]](https://github.com/fatih/vim-go/pull/2556)\n* Expand struct variable correctly in the variables debug window.\n  [[GH-2574]](https://github.com/fatih/vim-go/pull/2574)\n* Show output from errcheck when there are failures other than problems it can\n  report.\n  [[GH-2667]](https://github.com/fatih/vim-go/pull/2667)\n\n## v1.21 - (September 11, 2019)\n\nBACKWARDS INCOMPATIBILITIES:\n* `g:go_metalinter_disabled` has been removed.\n  [[GH-2375]](https://github.com/fatih/vim-go/pull/2375)\n\nIMPROVEMENTS:\n* Add a new option, `g:go_code_completion_enabled`, to control whether omnifunc\n  is set.\n  [[GH-2229]](https://github.com/fatih/vim-go/pull/2229)\n* Use build tags with golangci-lint.\n  [[GH-2261]](https://github.com/fatih/vim-go/pull/2261)\n* Allow debugging of packages outside of GOPATH without a go.mod file.\n  [[GH-2269]](https://github.com/fatih/vim-go/pull/2269)\n* Show which example failed when Example tests fail\n  [[GH-2277]](https://github.com/fatih/vim-go/pull/2277)\n* Show function signature and return types in preview window when autocompleting functions and methods.\n  [[GH-2289]](https://github.com/fatih/vim-go/pull/2289)\n* Improve the user experience when using null modules.\n  [[GH-2300]](https://github.com/fatih/vim-go/pull/2300)\n* Modify `:GoReportGitHubIssue` to include vim-go configuration values\n  [[GH-2323]](https://github.com/fatih/vim-go/pull/2323)\n* Respect `g:go_info_mode='gopls'` in go#complete#GetInfo.\n  [[GH-2313]](https://github.com/fatih/vim-go/pull/2313)\n* Allow `:GoLint`, `:GoErrCheck`, and `:GoDebug` to work in null modules.\n  [[GH-2335]](https://github.com/fatih/vim-go/pull/2335)\n* Change default value for `g:go_info_mode` and `g:go_def_mode` to `'gopls'`.\n  [[GH-2329]](https://github.com/fatih/vim-go/pull/2329)\n* Add a new option, `g:go_doc_popup_window` to optionally use a popup window\n  for godoc in Vim 8.1.1513 and later.\n  [[GH-2347]](https://github.com/fatih/vim-go/pull/2347)\n* Add `:GoAddWorkspace` function to support multiple workspaces with gopls.\n  [[GH-2356]](https://github.com/fatih/vim-go/pull/2356)\n* Install gopls from its stable package.\n  [[GH-2360]](https://github.com/fatih/vim-go/pull/2360)\n* Disambiguate progress message when initializing gopls.\n  [[GH-2369]](https://github.com/fatih/vim-go/pull/2369)\n* Calculate LSP position correctly when on a line that contains multi-byte\n  characters before the position.\n  [[GH-2389]](https://github.com/fatih/vim-go/pull/2389)\n* Calculate Vim position correctly from LSP text position.\n  [[GH-2395]](https://github.com/fatih/vim-go/pull/2395)\n* Use the statusline to display gopls initialization status messages and only\n  echo the statuses when `g:go_echo_command_info` is set.\n  [[GH-2422]](https://github.com/fatih/vim-go/pull/2422)\n* Send configuration to gopls so that build tags will be considered and hover\n  content won't have documentation.\n  [[GH-2429]](https://github.com/fatih/vim-go/pull/2429)\n* Add a new option, `g:go_term_close_on_exit`, to control whether jobs run in a\n  terminal window will close the terminal window when the job exits.\n  [[GH-2409]](https://github.com/fatih/vim-go/pull/2409)\n* Allow `g:go_template_file` and `g:go_template_test_files` to reside outside\n  of vim-go's template directory.\n  [[GH-2434]](https://github.com/fatih/vim-go/pull/2434)\n* Add a new command, `:GoLSPDebugBrowser`, to open a browser to gopls debugging\n  view.\n  [[GH-2436]](https://github.com/fatih/vim-go/pull/2436)\n* Restart gopls automatically when it is updated via `:GoUpdateBinaries`.\n  [[GH-2453]](https://github.com/fatih/vim-go/pull/2453)\n* Reset `'more'` while installing binaries to avoid unnecessary more prompts.\n  [[GH-2457]](https://github.com/fatih/vim-go/pull/2457)\n* Highlight `%w` as a format specifier (for Go 1.13).\n  [[GH-2433]](https://github.com/fatih/vim-go/pull/2433)\n* Handle changes to Go 1.13's go vet output that gometalinter isn't expecting.\n  [[GH-2475]](https://github.com/fatih/vim-go/pull/2475)\n* Make `golangci-lint` the default value for `g:go_metalinter_command`.\n  [[GH-2478]](https://github.com/fatih/vim-go/pull/2478)\n* Parse compiler errors from Go 1.13 `go vet` correctly.\n  [[GH-2485]](https://github.com/fatih/vim-go/pull/2485)\n\nBUG FIXES:\n* display info about function and function types whose parameters are\n  `interface{}` without truncating the function signature.\n  [[GH-2244]](https://github.com/fatih/vim-go/pull/2244)\n* install tools that require GOPATH mode when in module mode.\n  [[GH-2253]](https://github.com/fatih/vim-go/pull/2253)\n* Detect GOPATH when starting `gopls`\n  [[GH-2255]](https://github.com/fatih/vim-go/pull/2255)\n* Handle `gopls` responses in the same window from which the respective request\n  originated.\n  [[GH-2266]](https://github.com/fatih/vim-go/pull/2266)\n* Show completion matches from gocode.\n  [[GH-2267]](https://github.com/fatih/vim-go/pull/2267)\n* Show the completion preview window.\n  [[GH-2268]](https://github.com/fatih/vim-go/pull/2268)\n* Set the anchor for method documentation correctly.\n  [[GH-2276]](https://github.com/fatih/vim-go/pull/2276)\n* Respect the LSP information for determining where candidate matches start.\n  [[GH-2291]](https://github.com/fatih/vim-go/pull/2291)\n* Restore environment variables with backslashes correctly.\n  [[GH-2292]](https://github.com/fatih/vim-go/pull/2292)\n* Modify handling of gopls output for `:GoInfo` to ensure the value will be\n  displayed.\n  [[GH-2311]](https://github.com/fatih/vim-go/pull/2311)\n* Run `:GoLint` successfully in null modules.\n  [[GH-2318]](https://github.com/fatih/vim-go/pull/2318)\n* Ensure actions on save work in new buffers that have not yet been persisted to disk.\n  [[GH-2319]](https://github.com/fatih/vim-go/pull/2319)\n* Restore population of information in `:GoReportGitHubIssue`.\n  [[GH-2312]](https://github.com/fatih/vim-go/pull/2312)\n* Do not jump back to the originating window when jumping to definitions with\n  `g:go_def_mode='gopls'`.\n  [[GH-2327]](https://github.com/fatih/vim-go/pull/2327)\n* Fix getting information about a valid identifier for which gopls returns no\n  information (e.g. calling `:GoInfo` on a package identifier).\n  [[GH-2339]](https://github.com/fatih/vim-go/pull/2339)\n* Fix tab completion of package names on the cmdline in null modules.\n  [[GH-2342]](https://github.com/fatih/vim-go/pull/2342)\n* Display identifier info correctly when the identifier has no godoc.\n  [[GH-2373]](https://github.com/fatih/vim-go/pull/2373)\n* Fix false positives when saving a buffer and `g:go_metalinter_command` is\n  `golangci-lint`.\n  [[GH-2367]](https://github.com/fatih/vim-go/pull/2367)\n* Fix `:GoDebugRestart`.\n  [[GH-2390]](https://github.com/fatih/vim-go/pull/2390)\n* Do not execute tests twice in terminal mode.\n  [[GH-2397]](https://github.com/fatih/vim-go/pull/2397)\n* Do not open a new buffer in Neovim when there are compilation errors and\n  terminal mode is enabled.\n  [[GH-2401]](https://github.com/fatih/vim-go/pull/2401)\n* Fix error due to typo in implementation of `:GoAddWorkspace`.\n  [[GH-2415]](https://github.com/fatih/vim-go/pull/2401)\n* Do not format the file automatically when `g:go_format_autosave` is set and\n  the file being written is not the current file.\n  [[GH-2442]](https://github.com/fatih/vim-go/pull/2442)\n* Fix `go-debug-stepout` mapping.\n  [[GH-2464]](https://github.com/fatih/vim-go/pull/2464)\n* Handle paths with spaces correctly when executing jobs.\n  [[GH-2472]](https://github.com/fatih/vim-go/pull/2472)\n* Remove a space in the default value for `g:go_debug_log_output`, so that\n  Delve will start on Windows.\n  [[GH-2480]](https://github.com/fatih/vim-go/pull/2480)\n\n## 1.20 - (April 22, 2019)\n\nFEATURES:\n* ***gopls support!***\n  * use gopls for autocompletion by default in Vim8 and Neovim.\n  * use gopls for `:GoDef` by setting `g:go_def_mode='gopls'`.\n  * use gopls for `:GoInfo` by setting `g:go_info_mode='gopls'`.\n* Add support for golangci-lint.\n  * set `g:go_metalinter_command='golangci-lint'` to use golangci-lint instead\n    of gometalinter.\n* New `:GoDefType` command to jump to a type definition from an instance of the\n  type.\n\nBACKWARDS INCOMPATIBILITIES:\n* `g:go_highlight_function_arguments` is renamed to `g:go_highlight_function_parameters`\n  [[GH-2117]](https://github.com/fatih/vim-go/pull/2117)\n\nIMPROVEMENTS:\n* Disable `g:go_gocode_propose_source` by default.\n  [[GH-2050]](https://github.com/fatih/vim-go/pull/2050)\n* Don't spam users when Vim is run with vi compatibility.\n  [[GH-2055]](https://github.com/fatih/vim-go/pull/2055)\n* Add bang support to lint commands to allow them to be run without jumping to\n  errors.\n  [[GH-2056]](https://github.com/fatih/vim-go/pull/2056)\n* Use `go doc` for `:GoDoc` instead of `godoc`.\n  [[GH-2070]](https://github.com/fatih/vim-go/pull/2070)\n* Detach from and shutdown dlv correctly.\n  [[GH-2075]](https://github.com/fatih/vim-go/pull/2075)\n* Do not require `'autowrite'` or `'autowriteall'` to be set when using\n  autocompletion in module mode.\n  [[GH-2091]](https://github.com/fatih/vim-go/pull/2091)\n* Fix use of `g:go_metalinter_command` _and_ apply it even when autosaving.\n  [[GH-2101]](https://github.com/fatih/vim-go/pull/2101)\n* Report errors in quickfix when Delve fails to start (e.g. compiler errors).\n  [[GH-2111]](https://github.com/fatih/vim-go/pull/2111)\n* Support `'undo_ftplugin'`, make most autocmds buffer-local, and only do the\n  bare minimum based on file names alone.\n  [[GH-2108]](https://github.com/fatih/vim-go/pull/2108)\n* Write a message when `:GoInfo` can't display any results when `g:go_info_mode='gocode'`.\n  [[GH-2122]](https://github.com/fatih/vim-go/pull/2122)\n* Highlight fields followed by an operator when `g:go_highlight_fields` is set.\n  [[GH-1907]](https://github.com/fatih/vim-go/pull/1907)\n* Skip autosave actions when the buffer is not a readable file.\n  [[GH-2143]](https://github.com/fatih/vim-go/pull/2143)\n* Run `godef` from the current buffer's directory to make sure it works with modules.\n  [[GH-2150]](https://github.com/fatih/vim-go/pull/2150)\n* Add a function, `go#tool#DescribeBalloon`, to show information in a balloon\n  with `'balloonexpr'`. (Vim8 only).\n  [[GH-1975]](https://github.com/fatih/vim-go/pull/1975)\n* Add initial support for `gopls`.\n  [[GH-2163]](https://github.com/fatih/vim-go/pull/2163).\n* Add `:GoDefType` to jump to the type definition of the identifier under the\n  cursor.\n  [[GH-2165]](https://github.com/fatih/vim-go/pull/2165)\n* Notify gopls about changes.\n  [[GH-2171]](https://github.com/fatih/vim-go/pull/2171)\n* Respect `g:go_jump_to_error` when running `gometalinter` automatically on\n  save.  [[GH-2176]](https://github.com/fatih/vim-go/pull/2176)\n* Use gopls for code completion by default in Vim8 and Neovim.\n  [[GH-2172]](https://github.com/fatih/vim-go/pull/2172)\n* Add support for golangci-lint.\n  [[GH-2182]](https://github.com/fatih/vim-go/pull/2182)\n* Show hover balloon using gopls instead of gocode.\n  [[GH-2202]](https://github.com/fatih/vim-go/pull/2202)\n* Add a new option, `g:go_debug_log_output`, to control logging with the\n  debugger.\n  [[GH-2203]](https://github.com/fatih/vim-go/pull/2203)\n* Do not jump to quickfix or location list window when bang is used for async\n  jobs or linting.\n  [[GH-2205]](https://github.com/fatih/vim-go/pull/2205)\n* Tab complete package names for commands from vendor directories and in\n  modules.\n  [[GH-2213]](https://github.com/fatih/vim-go/pull/2213)\n* Add support for `gopls` to `g:go_info_mode`.\n  [[GH-2224]](https://github.com/fatih/vim-go/pull/2224)\n\nBUG FIXES:\n* Fix opening of non-existent file from `:GoDeclsDir` when the current\n  directory is not the directory containing the current buffer.\n  [[GH-2048]](https://github.com/fatih/vim-go/pull/2048)\n* Fix jumping to an identifier with godef from a modified buffer.\n  [[GH-2054]](https://github.com/fatih/vim-go/pull/2054)\n* Fix errors when `g:go_debug` contains `debugger-commands`.\n  [[GH-2075]](https://github.com/fatih/vim-go/pull/2075)\n* Fix errors from `:GoDebugStop` in Neovim.\n  [[GH-2075]](https://github.com/fatih/vim-go/pull/2075)\n* Fix `:GoSameIdsToggle`.\n  [[GH-2086]](https://github.com/fatih/vim-go/pull/2086)\n* Do not set fileencoding or fileformat options or populate from template when\n  the buffer is not modifiable.\n  [[GH-2097]](https://github.com/fatih/vim-go/pull/2097)\n* Do not clear buffer-local autocmds of other buffers. \n  [[GH-2109]](https://github.com/fatih/vim-go/pull/2109)\n* Highlight return parameter types when g:go_highlight_function_arguments is\n  set.  [[GH-2116]](https://github.com/fatih/vim-go/pull/2116)\n* Fix lockup in Neovim when trying to run `:GoDebugTest` when there are no\n  tests.  [[GH-2125]](https://github.com/fatih/vim-go/pull/2125)\n* Keep track of breakpoints correctly when buffer is edited after breakpoints\n  are set.\n  [[GH-2126]](https://github.com/fatih/vim-go/pull/2126)\n* Fix race conditions in `:GoDebugStop`.\n  [[GH-2127]](https://github.com/fatih/vim-go/pull/2127)\n* Fix jumping to module or package using godef.\n  [[GH-2141]](https://github.com/fatih/vim-go/pull/2141)\n* Fix errors caused by redefining functions within functions.\n  [[GH-2189]](https://github.com/fatih/vim-go/pull/2189)\n* Highlight pre-release and metadata in versions in go.mod.\n  [[GH-2192]](https://github.com/fatih/vim-go/pull/2192)\n* Handle runtime panics from `:GoRun` when using Neovim's terminal.\n  [[GH-2209]](https://github.com/fatih/vim-go/pull/2209)\n* Fix adding tag option when a tag is added.\n  [[GH-2227]](https://github.com/fatih/vim-go/pull/2227)\n\n## 1.19 - (November 4, 2018)\n\nFEATURES:\n\n* **go.mod file support!** This is the first feature for upcoming Go modules\n  support. The followings are added:\n  * Syntax highlighting for the `go.mod` file. \n  * A new `gomod` filetype is set if a `go.mod` file has been opened and starts\n    with the line `module `\n  * New **:GoModFmt** command that formats the `go.mod` file\n  * Auto format on save feature for `:GoModFmt`, enabled automatically. Can be\n    toggled of with the setting `g:go_mod_fmt_autosave` or with the command:\n    `GoModFmtAutoSaveToggle`\n    [[GH-1931]](https://github.com/fatih/vim-go/pull/1931)\n\nIMPROVEMENTS:\n* Unify async job handling for Vim8 and Neovim.\n  [[GH-1864]](https://github.com/fatih/vim-go/pull/1864)\n* Document Vim and Neovim requirements in README.md and help file.\n  [[GH-1889]](https://github.com/fatih/vim-go/pull/1889)\n* Highlight `context.Context` when `g:go_highlight_extra_types` is set.\n  [[GH-1903]](https://github.com/fatih/vim-go/pull/1903)\n* Run gometalinter asynchronously in Neovim.\n  [[GH-1901]](https://github.com/fatih/vim-go/pull/1901)\n* Run gorename asynchronously in Vim8 and Neovim.\n  [[GH-1894]](https://github.com/fatih/vim-go/pull/1894)\n* Install keyify from its canonical import path.\n  [[GH-1924]](https://github.com/fatih/vim-go/pull/1924)\n* Update the tested version of Neovim to v0.3.1.\n  [[GH-1923]](https://github.com/fatih/vim-go/pull/1923)\n* Run autocompletion asynchronously in Vim8 and Neovim.\n  [[GH-1926]](https://github.com/fatih/vim-go/pull/1926)\n* Show statusline update when running `:GoInfo` with `g:go_info_mode='gocode'`.\n  [[GH-1937]](https://github.com/fatih/vim-go/pull/1937)\n* Do not update statusline when highlighting sameids or showing type info via\n  an autocmd.\n  [[GH-1937]](https://github.com/fatih/vim-go/pull/1937)\n* Do not indent within a raw string literal.\n  [[GH-1858]](https://github.com/fatih/vim-go/pull/1858)\n* Highlight Go's predeclared function identifiers (the functions in `builtins`)\n  using keyword groups and highlight them using the `Identifiers` group.\n  [[GH-1939]](https://github.com/fatih/vim-go/pull/1939)\n* Add a new FAQ entry to instruct users how to modify the vim-go highlight\n  groups.\n  [[GH-1939]](https://github.com/fatih/vim-go/pull/1939)\n* Improve use of statusline and progress messages.\n  [[GH-1948]](https://github.com/fatih/vim-go/pull/1948)\n* Add `tt` snippet to create a table test boilerplate (see\n  https://github.com/golang/go/wiki/TableDrivenTests for more information on\n  how to use a table driven test).\n  [[GH-1956]](https://github.com/fatih/vim-go/pull/1956)\n* Add `<Plug>(go-decls)` and `<Plug>(go-decls-dir)` mappings.\n  [[GH-1964]](https://github.com/fatih/vim-go/pull/1964)\n* Handle go1.11 test output.\n  [[GH-1978]](https://github.com/fatih/vim-go/pull/1978)\n* Internal: install tools by their custom names\n  [[GH-1984]](https://github.com/fatih/vim-go/pull/1984)\n* Support the go-debugger features in Neovim.\n  [[GH-2007]](https://github.com/fatih/vim-go/pull/2007)\n* color the statusline for termguicolors and Neovim.\n  [[GH-2014]](https://github.com/fatih/vim-go/pull/2014)\n* add an option to disable highlighting of breakpoints and the current line\n  when debugging.\n  [[GH-2025]](https://github.com/fatih/vim-go/pull/2025)\n* Update autocompletion to work with Go modules.\n  [[GH-1988]](https://github.com/fatih/vim-go/pull/1988)\n* Add an option to search $GOPATH/bin or $GOBIN _after_ $PATH.\n  [[GH-2041]](https://github.com/fatih/vim-go/pull/2041)\n\nBUG FIXES:\n* Fix `:GoRun %` on Windows.\n  [[GH-1900]](https://github.com/fatih/vim-go/pull/1900)\n* Fix `go#complete#GetInfo()` to return a description of the identifier.\n  [[GH-1905]](https://github.com/fatih/vim-go/pull/1905)\n* Restore support for running tests in the Neovim terminal.\n  [[GH-1895]](https://github.com/fatih/vim-go/pull/1895)\n* Fix `:GoInfo` when `g:go_info_mode` is `gocode`\n  [[GH-1915]](https://github.com/fatih/vim-go/pull/1915)\n* Fix highlighting of pointer type in var blocks.\n  [[GH-1794]](https://github.com/fatih/vim-go/pull/1794)\n* Fix `:GoImport` when adding to an empty import block (i.e`import ()`)\n  [[GH-1938]](https://github.com/fatih/vim-go/pull/1938)\n* Run shell commands with shellcmdflag set to `-c`.\n  [[GH-2006]](https://github.com/fatih/vim-go/pull/2006)\n* Use the correct log output option for delve.\n  [[GH-1992]](https://github.com/fatih/vim-go/pull/1992)\n* Pass empty arguments correctly in async jobs on Windows.\n  [[GH-2011]](https://github.com/fatih/vim-go/pull/2011)\n* Don't close godoc scratch window when using arrow keys.\n  [[GH-2021]](https://github.com/fatih/vim-go/pull/2021)\n\nBACKWARDS INCOMPATIBILITIES:\n* Bump minimum required version of Vim to 7.4.2009.\n  [[GH-1899]](https://github.com/fatih/vim-go/pull/1899)\n* Switch gocode to github.com/mdempsky/gocode. Several gocode options have been\n  removed and a new one has been added.\n  [[GH-1853]](https://github.com/fatih/vim-go/pull/1853)\n\n## 1.18 - (July 18, 2018)\n\nFEATURES:\n\n* Add **:GoIfErr** command together with the `<Plug>(go-iferr)` plug key to\n  create a custom mapping. This command generates an `if err != nil { return ...  }` \n  automatically which infer the type of return values and the numbers.\n  For example:\n\n  ```\n  func doSomething() (string, error) {\n      f, err := os.Open(\"file\")\n  }\n  ```\n \n  Becomes:\n\n  ```\n  func doSomething() (string, error) {\n      f, err := os.Open(\"file\")\n      if err != nil {\n          return \"\", err\n      }\n  }\n  ```\n\n* Two new text objects has been added: \n  * `ic` (inner comment) selects the content of the comment, excluding the start/end markers (i.e: `//`, `/*`)\n  * `ac` (a comment) selects the content of the whole commment block, including markers\n  To use this new feature, make sure you use use the latest version of\n  [motion](https://github.com/fatih/motion). You can update the tool from Vim\n  via `:GoUpdateBinaries`\n  [[GH-1779]](https://github.com/fatih/vim-go/pull/1779)\n* Add `:GoPointsTo` to show all variables to which the pointer under the cursor\n  may point to.\n  [[GH-1751]](https://github.com/fatih/vim-go/pull/1751)\n* Add `:GoReportGitHubIssue` to initialize a new GitHub issue with as much data\n  that our template requests as possible.\n  [[GH-1738]](https://github.com/fatih/vim-go/pull/1738)\n\nIMPROVEMENTS:\n\n* Add build tags (with `g:go_build_tags`) to all commands that support it.\n  [[GH-1705]](https://github.com/fatih/vim-go/pull/1705)\n* Some command which operate on files (rather than Vim buffers) will now show a\n  warning if there are unsaved buffers, similar to Vim's `:make`.\n  [[GH-1754]](https://github.com/fatih/vim-go/pull/1754)\n* Don't return an error from `:GoGuru` functions when the import path is\n  unknown and scope is unneeded.\n  [[GH-1826]](https://github.com/fatih/vim-go/pull/1826)\n* Performance improvements for the `go.vim` syntax file.\n  [[GH-1799]](https://github.com/fatih/vim-go/pull/1799)\n* Allow `GoDebugBreakpoint` and `GoDebugCurrent` highlight groups to be\n  overridden by user configuration.\n  [[GH-1850]](https://github.com/vim-go/pull/1850)\n* Strip trailing carriage returns from quickfix errors that are parsed\n  manually. [[GH-1861]](https://github.com/fatih/vim-go/pull/1861).\n* Cleanup title of terminal window.\n  [[GH-1861]](https://github.com/fatih/vim-go/pull/1861).\n* Add `:GoImpl` is able to complete interfaces by their full import path in\n  addition to the current package name (i.e: `:GoImpl t *T github.com/BurntSushi/toml.Unmarshaller` \n  is now possible)\n  [[GH-1884]](https://github.com/fatih/vim-go/pull/1884)\n\nBUG FIXES:\n\n* Update the correct window's location list after a long running async job\n  completes, even when the user changes their window layout while the job is\n  running.\n  [[GH-1734]](https://github.com/fatih/vim-go/pull/1734)\n* Apply debugger mappings only for Go buffers, and not all buffers.\n  [[GH-1696]](https://github.com/fatih/vim-go/pull/1696)\n* The `gohtmltmpl` filetype will now highlight `{{ .. }}` syntax HTML attributes\n  and some other locations.\n  [[GH-1790]](https://github.com/fatih/vim-go/pull/1790)\n* Use the correct logging flag argument for delve.\n  [[GH-1809]](https://github.com/fatih/vim-go/pull/1809)\n* Fix gocode option string values that would cause gocode settings not to set\n  correctly\n  [[GH-1818]](https://github.com/fatih/vim-go/pull/1818)\n* Fix Neovim handling of guru output.\n  [[GH-1846]](https://github.com/fatih/vim-go/pull/1846)\n* Execute commands correctly when they are in $GOBIN but not $PATH.\n  [[GH-1866]](https://github.com/fatih/vim-go/pull/1866)\n* Open files correctly with ctrlp.\n  [[GH-1878]](https://github.com/fatih/vim-go/pull/1878)\n* Fix checking guru binary path \n  [[GH-1886]](https://github.com/fatih/vim-go/pull/1886)\n* Add build tags to `:GoDef` if only it's present \n  [[GH-1882]](https://github.com/fatih/vim-go/pull/1882)\n\n## 1.17 - (March 27, 2018)\n\nFEATURES:\n\n* **Debugger support!** Add integrated support for the\n  [`delve`](https://github.com/go-delve/delve) debugger. Use\n  `:GoInstallBinaries` to install `dlv`, and see `:help go-debug` to get\n  started.\n  [[GH-1390]](https://github.com/fatih/vim-go/pull/1390)\n\nIMPROVEMENTS:\n\n* Add descriptions to neosnippet abbrevations.\n  [[GH-1639]](https://github.com/fatih/vim-go/pull/1639)\n* Show messages in the location list instead of the quickfix list when\n  `gometalinter` is run automatically when saving a buffer. Whether the\n  location list or quickfix list is used can be customized in the usual ways.\n  [[GH-1652]](https://github.com/fatih/vim-go/pull/1652)\n* Redraw the screen before executing blocking calls to gocode.\n  [[GH-1671]](https://github.com/fatih/vim-go/pull/1671)\n* Add `fe` -> `fmt.Errorf()` snippet for NeoSnippet and UltiSnippets.\n  [[GH-1677]](https://github.com/fatih/vim-go/pull/1677)\n* Use the async api when calling guru from neovim.\n  [[GH-1678]](https://github.com/fatih/vim-go/pull/1678)\n* Use the async api when calling gocode to get type info.\n  [[GH-1697]](https://github.com/fatih/vim-go/pull/1697)\n* Cache import path lookups to improve responsiveness.\n  [[GH-1713]](https://github.com/fatih/vim-go/pull/1713)\n\nBUG FIXES:\n\n* Create quickfix list correctly when tests timeout.\n  [[GH-1633]](https://github.com/fatih/vim-go/pull/1633)\n* Apply `g:go_test_timeout` when running `:GoTestFunc`.\n  [[GH-1631]](https://github.com/fatih/vim-go/pull/1631)\n* The user's configured `g:go_doc_url` variable wasn't working correctly in the\n  case when the \"gogetdoc\" command isn't installed.\n  [[GH-1629]](https://github.com/fatih/vim-go/pull/1629)\n* Highlight format specifiers with an index (e.g. `%[2]d`).\n  [[GH-1634]](https://github.com/fatih/vim-go/pull/1634)\n* Respect `g:go_test_show_name` change for `:GoTest` when it changes during a\n  Vim session.\n  [[GH-1641]](https://github.com/fatih/vim-go/pull/1641)\n* Show `g:go_test_show_name` value for `:GoTest` failures if it's available.\n  [[GH-1641]](https://github.com/fatih/vim-go/pull/1641)\n* Make sure linter errors for the file being saved are shown in vim74 and nvim.\n  [[GH-1640]](https://github.com/fatih/vim-go/pull/1640)\n* Make sure only linter errors for the file being saved are shown in vim8.\n  Previously, all linter errors for all files in the current file's directory\n  were being shown.\n  [[GH-1640]](https://github.com/fatih/vim-go/pull/1640)\n* Make sure gometalinter is run on the given directories when arguments are\n  given to :GoMetaLinter.\n  [[GH-1640]](https://github.com/fatih/vim-go/pull/1640)\n* Do not run disabled linters with `gometalinter`.\n  [[GH-1648]](https://github.com/fatih/vim-go/pull/1648)\n* Do not prompt user to press enter after when `gometalinter` is called in\n  autosave mode.\n  [[GH-1654]](https://github.com/fatih/vim-go/pull/1654)\n* Fix potential race conditions when using vim8 jobs.\n  [[GH-1656]](https://github.com/fatih/vim-go/pull/1656)\n* Treat `'autowriteall'` the same as `'autowrite'` when determining whether to\n  write a buffer before calling some commands.\n  [[GH-1653]](https://github.com/fatih/vim-go/pull/1653)\n* Show the file location of test errors when the message is empty or begins\n  with a newline.\n  [[GH-1664]](https://github.com/fatih/vim-go/pull/1664)\n* Fix minisnip on Windows.\n  [[GH-1698]](https://github.com/fatih/vim-go/pull/1698)\n* Keep alternate filename when loading an autocreate template.\n  [[GH-1675]](https://github.com/fatih/vim-go/pull/1675)\n* Parse the column number in errors correctly in vim8 and neovim.\n  [[GH-1716]](https://github.com/fatih/vim-go/pull/1716)\n* Fix race conditions in the terminal handling for neovim.\n  [[GH-1721]](https://github.com/fatih/vim-go/pull/1721)\n* Put the user back in the original window regardless of the value of\n  `splitright` after starting a neovim terminal window.\n  [[GH-1725]](https://github.com/fatih/vim-go/pull/1725)\n\nBACKWARDS INCOMPATIBILITIES:\n\n* Highlighting function and method declarations/calls is fixed. To fix it we\n  had to remove the meaning of the previous settings. The following setting is\n  removed:\n\n  * `go_highlight_methods`\n\n  in favor of the following settings and changes:\n\n  * `go_highlight_functions`: This highlights now all function and method\n    declarations (whereas previously it would also highlight function and\n    method calls, not anymore)\n  * `go_highlight_function_calls`: This higlights now all all function and\n    method calls.\n  [[GH-1557]](https://github.com/fatih/vim-go/pull/1557)\n* Rename g`g:go_metalinter_excludes` to `g:go_metalinter_disabled`.\n  [[GH-1648]](https://github.com/fatih/vim-go/pull/1648)\n* `:GoBuild` doesn't append the `-i` flag anymore due the recent Go 1.10\n  changes that introduced a build cache.\n  [[GH-1701]](https://github.com/fatih/vim-go/pull/1701)\n\n## 1.16 - (December 29, 2017)\n\nFEATURES:\n\n* Add `g:go_doc_url` to change the `godoc` server from `godoc.org` to a custom\n  private instance. Currently only `godoc -http` instances are supported.\n  [[GH-1957]](https://github.com/fatih/vim-go/pull/1957).\n* New setting `g:go_test_prepend_name` (off by default) to add the failing test\n  name to the output of `:GoTest`\n  [[GH-1578]](https://github.com/fatih/vim-go/pull/1578).\n* Support [denite.vim](https://github.com/Shougo/denite.nvim) for `:GoDecls[Dir]`\n  [[GH-1604]](https://github.com/fatih/vim-go/pull/1604).\n\nIMPROVEMENTS:\n\n* `:GoRename` is a bit smarter when automatically pre-filling values, and what\n  gets pre-filled can be configured with `g:go_gorename_prefill` option.\n  In addition `:GoRename <Tab>` now lists some common options.\n  [[GH-1465]](https://github.com/fatih/vim-go/pull/1465).\n* Add support for `g:go_build_tags` to the `:GoTest` family of functions.\n  [[GH-1562]](https://github.com/fatih/vim-go/pull/1562).\n* Pass `--tests` to gometalinter when autosaving and when a custom gometalinter\n  command has not been set.\n  [[GH-1563]](https://github.com/fatih/vim-go/pull/1563).\n* Do not spam messages when command is run in a directory that does not exist.\n  [[GH-1527]](https://github.com/fatih/vim-go/pull/1527).\n* Run `syntax sync fromstart` after `:GoFmt`; this should make syntax\n  highlighting break slightly less often after formatting code\n  [[GH-1582]](https://github.com/fatih/vim-go/pull/1582).\n* `:GoDescribe` doesn't require a scope anymore\n  [[GH-1596]](https://github.com/fatih/vim-go/pull/1596).\n* Add some standard snippets for\n  [vim-minisnip](https://github.com/joereynolds/vim-minisnip)\n  [[GH-1589]](https://github.com/fatih/vim-go/pull/1589).\n* `g:go_snippet_engine` now defaults to `automatic` to use the first installed\n  snippet engine it can find.\n  [[GH-1589]](https://github.com/fatih/vim-go/pull/1589).\n* Make sure temporary files created for `:GoFmt` end with `.go` suffix as this\n  is required by some Go formatting tools\n  [[GH-1601]](https://github.com/fatih/vim-go/pull/1601).\n\nBUG FIXES:\n\n* Fix compatibility with Vim version before 7.4.1546\n  [[GH-1498]](https://github.com/fatih/vim-go/pull/1498).\n* Don't resize godoc window if it's already visible\n  [[GH-1488]](https://github.com/fatih/vim-go/pull/1488).\n* `:GoTestCompile` produces a test binary again. The test binary will be\n  written to a temporary directory to avoid polluting the user's working\n  directory. [[GH-1519]](https://github.com/fatih/vim-go/pull/1519)\n* Fix incorrect `:GoSameIdsToggle` behavior when there were match groups\n  present, but none were goSameId.\n  [[GH-1538]](https://github.com/fatih/vim-go/pull/1538)\n* Fix `gpl` snippet for UltiSnips.\n  [[GH-1535]](https://github.com/fatih/vim-go/pull/1535)\n* Fix test output processing to correctly handle panics and log statements.\n  [[GH-1513]](https://github.com/fatih/vim-go/pull/1513)\n* `:GoImpl` tab-completion would sometimes stop working\n  [[GH-1581]](https://github.com/fatih/vim-go/pull/1581).\n* Add `g:go_highlight_function_arguments` to highlight function arguments.\n  [[GH-1587]](https://github.com/fatih/vim-go/pull/1587).\n* Fix installation of `gocode` on MS-Windows.\n  [[GH-1606]](https://github.com/fatih/vim-go/pull/1606).\n* Fix template creation for files in directories that don't exist yet.\n  [[GH-1618]](https://github.com/fatih/vim-go/pull/1618).\n* Fix behavior of terminal windows and resize terminal windows correctly for\n  all valid `g:go_term_mode` values.\n  [[GH-1611]](https://github.com/fatih/vim-go/pull/1611).\n\nBACKWARDS INCOMPATIBILITIES:\n\n* Display a warning for Vim versions older than 7.4.1689. Older versions may\n  still work, but are not supported. You can use `let g:go_version_warning = 0`\n  to disable the warning.\n  [[GH-1524]](https://github.com/fatih/vim-go/pull/1524).\n* `g:go_autodetect_gopath` is *disabled* by default, as support for `vendor` has\n  been in Go for a while.<br>\n  Also change the implementation for `g:go_autodetect_gopath`; instead of manually\n  setting it before every command it will now be set with the `BufEnter` event,\n  and reset with the `BufLeave` event. This means that `$GOPATH` will be\n  changed for all commands run from Vim.\n  [[GH-1461]](https://github.com/fatih/vim-go/pull/1461) and\n  [[GH-1525]](https://github.com/fatih/vim-go/pull/1525).\n* Update `:GoFillStruct` to check the current line (vs. the exact cursor\n  position) for a struct literal to fill. To support this, fillstruct made\n  [backwards imcompatible\n  changes](https://github.com/davidrjenni/reftools/pull/8).\n  [[GH-1607]](https://github.com/fatih/vim-go/pull/1607).\n\n## 1.15 - (October 3, 2017)\n\nFEATURES:\n\n* Add `:GoFillStruct` to fill a struct with all fields; uses\n  [`fillstruct`](https://github.com/davidrjenni/reftools/tree/master/cmd/fillstruct)\n  [[GH-1443]](https://github.com/fatih/vim-go/pull/1443).\n\nIMPROVEMENTS:\n\n* `:GoAddTags` and `:GoRemoveTags` now continue to process if there are\n  malformed individual struct tags (run `:GoUpdateBinaries` to update\n  `gomodifiytags` binary) [[GH-1401]](https://github.com/fatih/vim-go/pull/1401)\n* `:GoAddTags` and `:GoRemoveTags` now shows a location list if there are\n  malformed struct tags (run `:GoUpdateBinaries` to update `gomodifiytags`\n  binary) [[GH-1401]](https://github.com/fatih/vim-go/pull/1401)\n* Add folding of the package-level comment (enabled by default) and/or any\n  other comments (disabled by default) [[GH-1377]](https://github.com/fatih/vim-go/pull/1377).\n  [[GH-1428]](https://github.com/fatih/vim-go/pull/1428).\n* Allow using :GoImpl on the type and struct parts too. Makes it a wee bit\n  easier to use [[GH-1386]](https://github.com/fatih/vim-go/pull/1386)\n* `:GoDef` sets the path of new buffers as relative to the current directory\n  when appropriate, instead of always using the full path [[GH-1277]](https://github.com/fatih/vim-go/pull/1277).\n* Syntax highlighting for variable declarations and assignments (disabled by default)\n  [[GH-1426]](https://github.com/fatih/vim-go/pull/1426) and\n  [[GH-1458]](https://github.com/fatih/vim-go/pull/1458).\n* Add support for `:GoDecls[Dir]` in [unite.vim](https://github.com/Shougo/unite.vim)\n  [[GH-1391]](https://github.com/fatih/vim-go/pull/1391).\n* Add support for [fzf.vim](https://github.com/junegunn/fzf.vim) in\n  `GoDecls[Dir]`.\n  [[GH-1437]](https://github.com/fatih/vim-go/pull/1437).\n* Support relative imports for `:GoImpl` [[GH-1322]](https://github.com/fatih/vim-go/pull/1322).\n* A new `g:go_list_type_commands` setting is added to individually set the list type for each command [[GH-1415]](https://github.com/fatih/vim-go/pull/1415). As en example:\n\n        let g:go_list_type_commands = {\"GoBuild\": \"quickfix\", \"GoTest\": \"locationlist\"}\n* Show unexpected errors better by expanding newlines and tabs\n  [[GH-1456]](https://github.com/fatih/vim-go/pull/1456).\n* `:GoInstallBinaries` and `:GoUpdateBinaries` can now install/update only the\n  selected binaries (e.g. `:GoUpdateBinaries guru golint`)\n  [[GH-1467]](https://github.com/fatih/vim-go/pull/1467).\n\nBUG FIXES:\n\n* `:GoFmt` now (again) uses `locationlist` to show formatting errors instead of\n  `quickfix`. To change back to `locationlist` you can change it with the\n  setting `let g:go_list_type_commands = { \"GoFmt\": locationlist\" }` [[GH-1415]](https://github.com/fatih/vim-go/pull/1415)\n* Include comments in import block when folding is enabled [[GH-1387]](https://github.com/fatih/vim-go/pull/1387)\n* Fix opening definitions in tabs [[GH-1400]](https://github.com/fatih/vim-go/pull/1400)\n* Fix accidentally closing quickfix window from other commands if :GoFmt or autosave format was called [[GH-1407]](https://github.com/fatih/vim-go/pull/1407)\n* Fix entering into insert mode after for term mode in nvim [[GH-1411]](https://github.com/fatih/vim-go/pull/1411)\n* When using :GoImpl on type foo struct{} it would work, but with:\n\n        type foo struct{\n        }\n\n  or with a struct with fields, it would create the generated methods inside the\n  struct [[GH-1386]](https://github.com/fatih/vim-go/pull/1386)\n* `:GoImpl` output would include extra newline, and error would include\n  trailing newline from shell command: `vim-go: invalid receiver: \"} *}\"<00>`.\n  Fixed with [[GH-1386]](https://github.com/fatih/vim-go/pull/1386)\n* Run `:GoMetaLinter` against the package of the open file [[GH-1414]](https://github.com/fatih/vim-go/pull/1414).\n* The `g:go_doc_command` and `g:go_doc_options` to configure the command for\n  `:GoDoc` were documented but never referenced [[GH-1420]](https://github.com/fatih/vim-go/pull/1420).\n* `go#package#FromPath()` didn't work correctly [[GH-1435]](https://github.com/fatih/vim-go/pull/1435).\n* Fix race condition for `guru` based commands [[GH-1439]](https://github.com/fatih/vim-go/pull/1439).\n* The `gohtmltmpl` filetype now sources the `html` ftplugin, so that `matchit`,\n  completion, and some other things work better.\n  [[GH-1442]](https://github.com/fatih/vim-go/pull/1442)\n* Fix `:GoBuild` shell escaping [[GH-1450]](https://github.com/fatih/vim-go/pull/1450).\n* Ensure fmt list gets closed when title cannot be checked [[GH-1474]](https://github.com/fatih/vim-go/pull/1474).\n\nBACKWARDS INCOMPATIBILITIES:\n\n* `:GoMetaLinter` now runs against the package of the open file instead of the\n  current working directory. This is so all commands behave the same relative\n  to the current open buffer. [[GH-1414]](https://github.com/fatih/vim-go/pull/1414)\n\n* `:GoImpl` now requires [`impl`](https://github.com/josharian/impl) version\n  3fb19c2c or newer (released June 13, 2017); use `:GoUpdateBinaries` to make\n  sure that you've got a recent version [[GH-1322]](https://github.com/fatih/vim-go/pull/1322)\n\n## 1.14 - (August 6, 2017)\n\nFEATURES:\n\n* We now have folding support based on Go syntax. To enable it you have to set\n  the following Vim setting: `set foldmethod=syntax`. Currently it folds blocks\n  (`{ }`), `import`, `var`, and `const` blocks, and package-level comments.\n  These can be individually disabled/enabled if desired. For more info please\n  read the documentation for the `g:go_fold_enable` setting. [[GH-1339]](https://github.com/fatih/vim-go/pull/1339)\n  [[GH-1377]](https://github.com/fatih/vim-go/pull/1377)\n* `:GoFiles` accepts now an argument to change the type of files it can show.\n  By default it shows`.go source files` but now it can be changed to show\n  various kind of files. The full list can be seen via `go list --help` under\n  the `// Source Files` section [[GH-1372]](https://github.com/fatih/vim-go/pull/1372) i.e:\n\n```\n:GoFiles CgoFiles        // shows .go sources files that import \"C\"\n:GoFiles TestGoFiles     // shows _test.go files in package\n:GoFiles IgnoredGoFiles  // shows .go sources ignored due to build constraints\netc..\n```\n\nIMPROVEMENTS\n\n* Files created with `_test.go` extension have a new template with a ready to\n  go test function. The template can be changed with the\n  `g:go_template_test_file` setting. [[GH-1318]](https://github.com/fatih/vim-go/pull/1318)\n* Improve performance for highly used operations by caching `go env` calls [[GH-1320]](https://github.com/fatih/vim-go/pull/1320)\n* `:GoCoverage` can accept arguments now. i.e: `:GoCoverage -run TestFoo` [[GH-1326]](https://github.com/fatih/vim-go/pull/1326)\n* `:GoDecls` and `:GoDeclsDir` shows a warning if [ctrlp.vim](https://github.com/ctrlpvim/ctrlp.vim) is not installed\n* `:GoBuild` now compiles the package with the `-i` flag added. This means that subsequent calls are much more faster due caching of packages [[GH-1330]](https://github.com/fatih/vim-go/pull/1330)\n* `:GoCoverage` echos now the progress if `g:go_echo_command_info` is enabled [[GH-1333]](https://github.com/fatih/vim-go/pull/1333)\n* Add `g:go_doc_max_height` setting to control the maximum height of the window created by `:GoDoc` and `K` mapping [[GH-1335]](https://github.com/fatih/vim-go/pull/1335)\n* The `af` text object is able to include the assignment variable for anonymous functions. Can be disabled with `g:go_textobj_include_variable = 0` [[GH-1345]](https://github.com/fatih/vim-go/pull/1345)\n* Add `g:go_list_autoclose` setting to prevent closing the quickfix/location list after zero items [[GH-1361]](https://github.com/fatih/vim-go/pull/1361)\n* Cursor is now adjusted and locked to the correct line when `goimports` is used for autosave [[GH-1367]](https://github.com/fatih/vim-go/pull/1367)\n* Complement the path of command for different situations of Cygwin environment [[GH-1394]](https://github.com/fatih/vim-go/pull/1394)\n* Show message when using :GoDef and opening a new buffer [[GH-1385]](https://github.com/fatih/vim-go/pull/1385)\n\n\nBUG FIXES:\n\n* Fix obtaining package's import path for the current directory. This fixes some issues we had if the user was using multiple GOPATH's [[GH-1321]](https://github.com/fatih/vim-go/pull/1321)\n* Fix documentation for vim-go & syntastic integration for errcheck using [[GH-1323]](https://github.com/fatih/vim-go/pull/1323)\n* Fix showing an output if a test has finished when `:GoTest` is called [[GH-1327]](https://github.com/fatih/vim-go/pull/1327)\n* Fix warning when goimports doesn't support srcdir [[GH-1344]](https://github.com/fatih/vim-go/pull/1344)\n* Fix broken code folding with go_highlight_types [[GH-1338]](https://github.com/fatih/vim-go/pull/1338)\n* Fix blocking the ui when swapfile is enabled and `:GoFmt` is called (either manually or via autosave) [[GH-1362]](https://github.com/fatih/vim-go/pull/1362)\n* Fix getting bin paths for binaries if GOPATH was not set and Go version =>1.7 was used [[GH-1363]](https://github.com/fatih/vim-go/pull/1363)\n* Fix picking up the correct list type for showing `:GoFmt` errors [[GH-1365]](https://github.com/fatih/vim-go/pull/1365)\n* Fix auto detecting of GOPATH for import paths with string 'src' (i.e: `GOPATH/src/github.com/foo/src/bar`) [[GH-1366]](https://github.com/fatih/vim-go/pull/1366)\n* Fix showing an empty window if `gogetdoc` was not found [[GH-1379]](https://github.com/fatih/vim-go/pull/1379)\n* Fix commands not being executed if paths would include spaces (binary name, GOPATH, file itself, etc..)  [[GH-1374]](https://github.com/fatih/vim-go/pull/1374)\n* Fix showing correct message when editing a new file [[GH-1371]](https://github.com/fatih/vim-go/pull/1371)\n* Fix filepaths in the quickfix list for :GoVet [[GH-1381]](https://github.com/fatih/vim-go/pull/1381)\n* Run :GoLint against the package of the open file [[GH-1382]](https://github.com/fatih/vim-go/pull/1382)\n\nBACKWARDS INCOMPATIBILITIES:\n\n* `:GoFmt` now uses `quickfix` to show formatting errors instead of\n  `locationlist`. To change back to `locationlist` you can change it with the\n  setting `let g:go_list_type = \"locationlist\"` [[GH-1365]](https://github.com/fatih/vim-go/pull/1365)\n* `:GoLint` now runs against the package of the open file instead of the\n  current working directory. This is so all commands behave the same relative\n  to the current open buffer. For more info check the [comment\n  here](https://github.com/fatih/vim-go/issues/1375#issuecomment-317535953)\n  [[GH-1382]](https://github.com/fatih/vim-go/pull/1382)\n\n## 1.13 - (June 6, 2017)\n\nFEATURES:\n\n* New `:GoKeyify` command that turns unkeyed struct literals into keyed struct literals. [[GH-1258]](https://github.com/fatih/vim-go/pull/1258). i.e:\n\n```\nExample{\"foo\", \"bar\", \"qux\"}\n```\n\nwill be converted to:\n\n```\nExample{\n  foo: \"foo\",\n  bar: \"bar\",\n  qux: \"qux\",\n}\n```\n\nCheckout the demo here: https://twitter.com/fatih/status/860410299714764802\n\n\n* New `g:go_addtags_transform` setting to change the transform rule (snakecase, camelcase, etc..) for `:GoAddTags` command [[GH-1275]](https://github.com/fatih/vim-go/pull/1275)\n* New snippet shortcut assigned to `ife` that expands to `if err := foo(); err != nil { ... }` [[GH-1268]](https://github.com/fatih/vim-go/pull/1268)\n\nIMPROVEMENTS\n\n* :GoMetaLinter can now exclude linters with the new `g:go_metalinter_excludes` option [[GH-1253]](https://github.com/fatih/vim-go/pull/1253)\n* Override `<C-LeftMouse>` mapping so `:GoDef` is used by default (as we do the same for `CTRL-]`, `gd`, etc. [[GH-1264]](https://github.com/fatih/vim-go/pull/1264)\n* add support for `go_list_type` setting in `:GoFmt` and `:GoImports` commands [[GH-1304]](https://github.com/fatih/vim-go/pull/1304)\n* add support for `go_list_type` setting in `:GoMetaLinter` commands [[GH-1309]](https://github.com/fatih/vim-go/pull/1309)\n* `go_fmt_options` can be now a dictionary to allow us to specifcy the\n  options for multiple binaries [[GH-1308]](https://github.com/fatih/vim-go/pull/1308). i.e:\n\n```\n  let g:go_fmt_options = {\n    \\ 'gofmt': '-s',\n    \\ 'goimports': '-local mycompany.com',\n    \\ }\n```\n* If win-vim(x64) with Cygwin is used, `cygpath` is used for constructing the paths [[GH-1092]](https://github.com/fatih/vim-go/pull/1092)\n\nBUG FIXES:\n\n* job: fix race between channel close and job exit [[GH-1247]](https://github.com/fatih/vim-go/pull/1247)\n* internal: fix system calls when using tcsh [[GH-1276]](https://github.com/fatih/vim-go/pull/1276)\n* path: return the unmodified GOPATH if autodetect is disabled [[GH-1280]](https://github.com/fatih/vim-go/pull/1280)\n* fix jumping to quickfix window when autom gometalinter on save was enabled [[GH-1293]](https://github.com/fatih/vim-go/pull/1293)\n* fix highlighting for `interface` and `structs` words when `go_highlight_types` is enabled [[GH-1301]](https://github.com/fatih/vim-go/pull/1301)\n* fix cwd for running `:GoRun` when used with neovim [[GH-1296]](https://github.com/fatih/vim-go/pull/1296)\n* `:GoFmt` handles files that are symlinked into GOPATH better (note that this behaviour is discouraged, but we're trying our best to handle all edge case :)) [[GH-1310]](https://github.com/fatih/vim-go/pull/1310)\n* `:GoTest` is able to parse error messages that include a colon `:` [[GH-1316]](https://github.com/fatih/vim-go/pull/1316)\n* `:GoTestCompile` under the hood doesn't produces a test binary anymore. Sometimes a race condition would happen which would not delete the test binary. [[GH-1317]](https://github.com/fatih/vim-go/pull/1317)\n* `:GoDef` jumps now to definition for build tags defined with `:GoBuildTags` (only guru) [[GH-1319]](https://github.com/fatih/vim-go/pull/1319)\n\nBACKWARDS INCOMPATIBILITIES:\n\n* `:GoLint` works on the whole directory instead of the current file. To use it for the current file give it as an argument, i.e `:GoLint foo.go` [[GH-1295]](https://github.com/fatih/vim-go/pull/1295)\n* `go_snippet_case_type` is removed in favor of the new `go_addtags_transform` setting [[GH-1299]](https://github.com/fatih/vim-go/pull/1299)\n* `go_imports_bin` is removed to avoid confusion as it would lead to race\n  conditions when set to `gofmt` along with the usage of `go_fmt_command`\n  [[GH-1212]](https://github.com/fatih/vim-go/pull/1212) [[GH-1308]](https://github.com/fatih/vim-go/pull/1308)\n* commands such as `:GoTest` has been refactored for easy maintainability. If\n  you use any custom script that was using the function `go#cmd#Test`, it\n  should be renamed to `go#test#Test`\n\n## 1.12 - (March 29, 2017)\n\nFEATURES:\n\n* New `:GoAddTags` and `:GoRemoveTags` command based on the tool\n  [gomodifytags](https://github.com/fatih/gomodifytags). This fixes many old\n  bugs that were due prior regexp based implementation. For the usage please\n  read the docs and checkout the demo at:\n  https://github.com/fatih/vim-go/pull/1204 [[GH-1204]](https://github.com/fatih/vim-go/pull/1204)\n* Add new `errl` snippet that expands to [[GH-1185]](https://github.com/fatih/vim-go/pull/1185):\n\n```\nif err != nil {\n  log.Fatal(err)\n}\n```\n* New `:GoBuildTags` command to change build tags for tools such as `guru`,\n  `gorename`, etc ... There is also a new setting called `g:go_build_tags`\n  [[GH-1232]](https://github.com/fatih/vim-go/pull/1232)\n\nIMPROVEMENTS:\n\n* vim-go works now even if GOPATH is not set (starting with Go 1.8) [[GH-1248]](https://github.com/fatih/vim-go/pull/1248)\n* Lowercase `<Leader>` in mappings examples for consistent documentation across the README [[GH-1192]](https://github.com/fatih/vim-go/pull/1192)\n* All of files should be written in utf-8 if the file will be passed to external command. [[GH-1184]](https://github.com/fatih/vim-go/pull/1184)\n* `:GoAddTags` is now able to add options to existing tags with the syntax\n  `:GoAddTags key,option`, i.e: `:GoAddTags json,omitempty` [[GH-985]](https://github.com/fatih/vim-go/pull/985)\n* Document 'noshowmode' requirement for echo_go_info [[GH-1197]](https://github.com/fatih/vim-go/pull/1197)\n* Improve godoc view for vertical splits [[GH-1195]](https://github.com/fatih/vim-go/pull/1195)\n* Set GOPATH for both possible go guru execution paths (sync and async) [[GH-1193]](https://github.com/fatih/vim-go/pull/1193)\n* Improve docs for :GoDef usage [[GH-1242]](https://github.com/fatih/vim-go/pull/1242)\n* Highlight trimming syntax for Go templates [[GH-1235]](https://github.com/fatih/vim-go/pull/1235)\n\nBUG FIXES:\n\n* Honor `g:go_echo_command_info` when dispatching builds in neovim [[GH-1176]](https://github.com/fatih/vim-go/pull/1176)\n* Fix `:GoBuild` error in neovim due to invalid jobcontrol handler function\n  signatures (`s:on_stdout`, `s:on_stderr`)[[GH-1176]](https://github.com/fatih/vim-go/pull/1176)\n* Update statusline before and after `go#jobcontrol#Spawn` command is executed [[GH-1176]](https://github.com/fatih/vim-go/pull/1176)\n* Correctly report the value of the 'g:go_guru_tags' variable [[GH-1177]](https://github.com/fatih/vim-go/pull/1177)\n* Ensure no trailing `:` exist in GOPATH detection if initial GOPATH is not set [[GH-1194]](https://github.com/fatih/vim-go/pull/1194)\n* Fix `:GoAddTags` to allow modifying existing comments [[GH-984]](https://github.com/fatih/vim-go/pull/984)\n* Fix `:GoAddTags` to work with nested structs [[GH-990]](https://github.com/fatih/vim-go/pull/990)\n* Fix `:GoAddTags` adding tags twice for existing tags [[GH-1064]](https://github.com/fatih/vim-go/pull/1064)\n* Fix `:GoAddTags` not working for fields of types `interface{}` [[GH-1091]](https://github.com/fatih/vim-go/pull/1091)\n* Fix `:GoAddTags` not working for fields with one line comments [[GH-1181]](https://github.com/fatih/vim-go/pull/1181)\n* Fix `:GoAddTags` not working if any field comment would contain `{}` [[GH-1189]](https://github.com/fatih/vim-go/pull/1189)\n* Respect go_fmt_options when running goimports [[GH-1211]](https://github.com/fatih/vim-go/pull/1211)\n* Set the filename in the location-list when there is an error with :GoFmt [[GH-1199]](https://github.com/fatih/vim-go/pull/1199)\n* Fix `:GoInstall` to accept additional arguments if async mode was enabled [[GH-1246]](https://github.com/fatih/vim-go/pull/1246)\n\nBACKWARDS INCOMPATIBILITIES:\n\n* The command `:GoGuruTags` is removed in favour of the new command\n  `:GoBuildTags`. This command will be used now not just for `guru`, also for\n  all new commands such as `gorename` [[GH-1232]](https://github.com/fatih/vim-go/pull/1232)\n* The setting `g:go_guru_tags` is removed in favour of the new setting\n  `g:go_build_tags` [[GH-1232]](https://github.com/fatih/vim-go/pull/1232)\n\n\n## 1.11 - (January 9, 2017)\n\nFEATURES:\n\n* Travis test integration has been added. Now any file that is added as\n  `<name>_test.vim` will be automatically tested in for every Pull Request\n  (just like how we add tests to Go with `_test.go`). Going forward this will\n  tremendously increase the stability and decrease the maintenance burden of\n  vim-go. [[GH-1157]](https://github.com/fatih/vim-go/pull/1157)\n* Add new `g:go_updatetime` setting to change the default updatetime (which was hardcoded previously) [[GH-1055]](https://github.com/fatih/vim-go/pull/1055)\n* Add new `g:go_template_use_pkg` setting to enable to use cwd as package name instead of basic template file [[GH-1124]](https://github.com/fatih/vim-go/pull/1124)\n\nIMPROVEMENTS:\n\n* Add `statusline` support for `:GoMetaLinter` [[GH-1120]](https://github.com/fatih/vim-go/pull/1120)\n* Quickfix and Location lists contain now a descriptive title (requires at least Vim `7.4.2200`)[[GH-1004]](https://github.com/fatih/vim-go/pull/1004)\n* Check `go env GOPATH` as well for `:GoInstallBinaries` as Go has now a default path for GOPATH (\"~/go\")starting with 1.8 [[GH-1152]](https://github.com/fatih/vim-go/pull/1152)\n* `:GoDocBrowser` now also works on import paths [[GH-1174]](https://github.com/fatih/vim-go/pull/1174)\n\nBUG FIXES:\n\n* Always use full path to detect packages to be shown in statusline [[GH-1121]](https://github.com/fatih/vim-go/pull/1121)\n* Use `echom` to persist errors in case of multiple echos [[GH-1122]](https://github.com/fatih/vim-go/pull/1122)\n* Fix a race condition where a quickfix window was not closed if a job has succeeded [[GH-1123]](https://github.com/fatih/vim-go/pull/1123)\n* Do not expand coverage arguments for non job execution of `:GoCoverage` [[GH-1127]](https://github.com/fatih/vim-go/pull/1127)\n* `:GoCoverage` doesn't mess up custom syntax anymore [[GH-1128]](https://github.com/fatih/vim-go/pull/1128)\n* Disable autoformat for `asm` files as they might be non Go ASM format [[GH-1141]](https://github.com/fatih/vim-go/pull/1141)\n* Fix indentation broken when using a action with a minus sign like `{{-` [[GH-1143]](https://github.com/fatih/vim-go/pull/1143)\n* Fix breaking Neovim change of passing less arguments to callbacks [[GH-1145]](https://github.com/fatih/vim-go/pull/1145)\n* Fix `guru` commands if custom build tags were set [[GH-1136]](https://github.com/fatih/vim-go/pull/1136)\n* Fix referencing a non defined variable for async commands when bang (!) was used\n* Fix `:GoDef` failing for a modified buffer if `hidden` was not set [[GH-1132]](https://github.com/fatih/vim-go/pull/1132)\n* Fix `:GoDefStack` to allow popping from jump list when buffer is modified [[GH-1133]](https://github.com/fatih/vim-go/pull/1133)\n* Improve internal defining of functions and referencing them for async operations [[GH-1155]](https://github.com/fatih/vim-go/pull/1155)\n* Fix `:GoMetaLinter` failing if `go_metalinter_command` is set. [[GH-1160]](https://github.com/fatih/vim-go/pull/1160)\n* Fix `:GoMetaLinter`'s `go_metalinter_deadline` setting for async mode [[GH-1146]](https://github.com/fatih/vim-go/pull/1146)\n\nBACKWARDS INCOMPATIBILITIES:\n\n* The following syntax options are now disabled by default. If you're using them be sure to set them in your .vimrc [[GH-1167]](https://github.com/fatih/vim-go/pull/1167)\n\n```viml\ng:go_highlight_array_whitespace_error\ng:go_highlight_chan_whitespace_error\ng:go_highlight_extra_types\ng:go_highlight_space_tab_error\ng:go_highlight_trailing_whitespace_error\n```\n\n\n\n## 1.10 (November 24, 2016)\n\nFEATURES:\n\n* **Vim 8.0 support!** This is the initial version to add Vim 8.0 based support to\n  all basic commands (check out below for more information). With time we'll\n  going to extend it to other commands. All the features are only enabled if\n  you have at least Vim 8.0.0087. Backwards compatible with Vim 7.4.x.\n  If you see any problems, please open an issue.\n\n* We have now a [logo for vim-go](https://github.com/fatih/vim-go/blob/master/assets/vim-go.png)! Thanks to @egonelbre for his work on this.\n* `:GoBuild`, `:GoTest`, `:GoTestCompile`, `:GoInstall` commands are now fully\n  async. Async means it doesn't block your UI anymore. If the command finished\n  it echoes the status. For a better experience use the statusline information\n  (more info below)\n\n* `:GoCoverage` and `:GoCoverageBrowser` commands are fully async.\n* `:GoDef` is fully async if `guru` is used as command.\n* `:GoRename` is fully async .\n\n* `:GoMetaLinter` is fully asnyc. Also works with the current autosave linting\n  feature. As a reminder, to enable auto linting on save either call\n  `:GoMetaLinterAutoSaveToggle` (temporary) or add `let\n  g:go_metalinter_autosave = 1` (persistent) to your virmc).\n\n* All `guru` commands run asynchronously if Vim 8.0 is being used. Current\n  Commands:\n  * GoImplements\n  * GoWhicherrs\n  * GoCallees\n  * GoDescribe\n  * GoCallers\n  * GoCallstack\n  * GoFreevars\n  * GoChannelPeers\n  * GoReferrers\n\n* `:GoSameIds` also runs asynchronously. This makes it useful especially for\n  auto sameids mode. In this mode it constantly evaluates the identifier under the\n  cursor whenever it's in hold position and then calls :GoSameIds. As a\n  reminder, to enable auto info either call `:GoSameIdsAutoToggle`(temporary)\n  or add `let g:go_auto_sameids = 1` (persistent) to your vimrc.\n\n* `:GoInfo` is now non blocking and works in async mode if `guru` is used in\n  `g:go_info_mode`. This makes it useful especially for autoinfo mode. In this\n  mode it constantly evaluates the identifier under the cursor whenever it's in\n  hold position and then calls :GoInfo. As a reminder, to enable auto info\n  either call `:GoAutoTypeInfoToggle`(temporary) or add `let\n  g:go_auto_type_info = 1` (persistent) to your vimrc. To use `guru` instead of\n  `gocode` add following to your vimrc: `let g:go_info_mode = 'guru'`\n\n  The `guru` is more accurate and reliabed due the usage of `guru` describe. It\n  doesn't rely on `pkg/` folder like `gocode` does. However it's slower than\n  `gocode` as there is no caching mechanism in `guru` yet.\n\n* **New**: Statusline function: `go#statusline#Show()` which can be plugged into\n  the statusline bar. Works only with vim 8.0. It shows all asynchronously\n  called functions status real time.  Checkout it in action:\n  https://twitter.com/fatih/status/800473735467847680. To enable it add the\n  following to your `vimrc`. If you use lightline, airline, .. check out their\n  respective documentation on how to add a custom function:\n\n```viml\n\" go command status (requires vim-go)\nset statusline+=%#goStatuslineColor#\nset statusline+=%{go#statusline#Show()}\nset statusline+=%*\n```\n\nIMPROVEMENTS:\n\n* **:GoDocBrowser** is now capable to to understand the identifier under the cursor (just like :GoDoc)\n* Function calls are now highlighted as well when `g:go_highlight_functions` is enabled [[GH-1048]](https://github.com/fatih/vim-go/pull/1048)\n* Add completion support for un-imported packages. This allows to complete even\n  if the package is not imported. By default it's disabled, enable by adding\n  `let g:go_gocode_unimported_packages = 1` [[GH-1084]](https://github.com/fatih/vim-go/pull/1084)\n* Tools that embeds GOROOT into their binaries do not work when people update\n  their Go version and the GOROOT contains the vesion as part of their path\n  (i.e: `/usr/local/Cellar/go/1.7.2/libexec`, [more\n  info](https://blog.filippo.io/stale-goroot-and-gorebuild/)) . This is now\n  fixed by introducing automatic GOROOT set/unset before each tool invoke.\n  [[GH-954]](https://github.com/fatih/vim-go/pull/954)\n* Added new setting `g:go_echo_go_info` to enable/disable printing identifier\n  information when completion is done [[GH-1101]](https://github.com/fatih/vim-go/pull/1101)\n* Added new `go_echo_command_info` setting is added, which is enabled by\n  default.  It's just a switch for disabling messages of commands, such as\n  `:GoBuild`, `:GoTest`, etc.. Useful to *disable* if `go#statusline#Show()` is\n  being used in Statusline, to prevent to see duplicates notifications.\n* goSameId highlighting is now linked to `Search`, which is much more clear as\n  it changes according to the users colorscheme\n* Add plug mapping `(go-lint)` for :GoLint [[GH-1089]](https://github.com/fatih/vim-go/pull/1089)\n\n\nBUG FIXES:\n\n* Change back nil and iota highlighting color to the old type [[GH-1049]](https://github.com/fatih/vim-go/pull/1049)\n* Fix passing arguments to `:GoBuild` while using NeoVim [[GH-1062]](https://github.com/fatih/vim-go/pull/1062)\n* Do not open a split if `:GoDef` is used on a modified file [[GH-1083]](https://github.com/fatih/vim-go/pull/1083)\n* Highlight nested structs correctly [[GH-1075]](https://github.com/fatih/vim-go/pull/1075)\n* Highlight builtin functions correctly if `g:go_highlight_functions` is enabled [[GH-1070]](https://github.com/fatih/vim-go/pull/1070)\n* Fix `:GoSameIds` highlighting if a new buffer is opened in the same window [[GH-1067]](https://github.com/fatih/vim-go/pull/1067)\n* Internal: add `abort` to all vim function to return in case of errors [[GH-1100]](https://github.com/fatih/vim-go/pull/1100)\n* Fix `:GoCoverage` to be executed if working dir is not inside the test dir [[GH-1033]](https://github.com/fatih/vim-go/pull/1033)\n\nBACKWARDS INCOMPATIBILITIES:\n\n* remove vim-dispatch and vimproc.vim support. vim 8.0 has now the necessary\n  API to invoke async jobs and timers. Going forward we should use those. Also\n  this will remove the burden to maintain compatibility with those plugins.\n\n* `go#jobcontrol#Statusline()` is removed in favor of the new, global and\n  extensible `go#statusline#Show()`\n\n## 1.9 (September 13, 2016)\n\nIMPROVEMENTS:\n\n* **guru** uses now the `-modified` flag, which allows us use guru on modified\n  buffers as well. This affects all commands where `guru` is used. Such as\n  `:GoDef`, `:GoReferrers`, etc.. [[GH-944]](https://github.com/fatih/vim-go/pull/944)\n* **:GoDoc** uses now the `-modified` flag under the hood (for `gogetdoc), which allows us to get documentation for the identifier under the cursor ina modified buffer. [[GH-1014]](https://github.com/fatih/vim-go/pull/1014)\n* Cleanup and improve documentation [[GH-987]](https://github.com/fatih/vim-go/pull/987)\n* Add new `g:go_gocode_socket_type` setting to change the underlying socket type passed to `gocode`. Useful to fallback to `tcp` on cases such as Bash on Windows [[GH-1000]](https://github.com/fatih/vim-go/pull/1000)\n* `:GoSameIds` is now automatically re-evaluated in cases of buffer reloads (such as `:GoRename`) [[GH-998]](https://github.com/fatih/vim-go/pull/998)\n* Improve docs about `go_auto_sameids` [[GH-1017]](https://github.com/fatih/vim-go/pull/1017)\n* Improve error message by printing the full path if an incompatible `goimports` is being used [[GH-1006]](https://github.com/fatih/vim-go/pull/1006)\n* `iota` and `nil` are now highlighted correctly and are not treated as booleans [[GH-1030]](https://github.com/fatih/vim-go/pull/1030)\n\nBUG FIXES:\n\n* Fix system calls on Windows [[GH-988]](https://github.com/fatih/vim-go/pull/988)\n* Fix :GoSameIds and :GoCoverage for light background and after changing color schemes [[GH-983]](https://github.com/fatih/vim-go/pull/983)\n* Fix TagBar and `GoCallers` for Windows user [[GH-999]](https://github.com/fatih/vim-go/pull/999)\n* Set updatetime for for `auto_sameids` feature as well [[GH-1016]](https://github.com/fatih/vim-go/pull/1016)\n* Update docs about missing `go_highlight_generate_tags` setting [[GH-1023]](https://github.com/fatih/vim-go/pull/1023)\n* Fix updating the jumplist if `:GoDef` is used [[GH-1029]](https://github.com/fatih/vim-go/pull/1029)\n* Fix highlighting literal percent sign (`%%`) in strings [[GH-1011]](https://github.com/fatih/vim-go/pull/1011)\n* Fix highlighting of nested fields [[GH-1007]](https://github.com/fatih/vim-go/pull/1007)\n* Fix checking for `exepath` feature for the upcoming vim 8.0 release [[GH-1046]](https://github.com/fatih/vim-go/pull/1046)\n\nBACKWARDS INCOMPATIBILITIES:\n\n* Rename `GoMetalinterAutoSaveToggle` to `GoMetaLinterAutoSaveToggle` to make it compatible with the existing `:GoMetaLinter` command [[GH-1020]](https://github.com/fatih/vim-go/pull/1020)\n\n## 1.8 (July 31, 2016)\n\nFEATURES:\n* New **`:GoAddTags`** command that adds field tags for the fields of a struct automatically based on the field names. Checkout the demo to see it in action: https://twitter.com/fatih/status/759822857773907968 [[GH-971]](https://github.com/fatih/vim-go/pull/971)\n* The snippet expansion `json` is now much more smarter. It pre populates the placeholder according to the first word and it also applies `snake_case` or `camelCase` conversion. Together with `:GoAddTags` it gives `vim-go` users flexible ways of populating a field tag. Checkout the demo to see it in action: https://twitter.com/fatih/status/754477622042689536 [[GH-927]](https://github.com/fatih/vim-go/pull/927)\n* New **`:GoSameIds`** command. When called highlights all same identifiers in the current file. Can be also enabled to highlight identifiers automatically (with `:GoSameIdsAutoToggle` or `g:go_auto_sameids`). Checkout the demo to see it in action: https://twitter.com/fatih/status/753673709278339072. [[GH-936]](https://github.com/fatih/vim-go/pull/936)\n* New **`:GoWhicherrs`** command. It shows all possible values of the selected error variable. [[GH-948]](https://github.com/fatih/vim-go/pull/948)\n* Add new `errp` snippet to expand an `if err != nil { panic() }` clause [[GH-926]](https://github.com/fatih/vim-go/pull/926)\n* If you open a new buffer with a Go filename it get automatically populated based on the directory. If there are no Go files a simple main package is created, otherwise the file will include the package declaration line based on the package in the current directory. Checkout the demo to see it in action: https://twitter.com/fatih/status/748333086643994624. This is enabled by default. Can be disabled with `let g:go_template_autocreate = 0`. You can use your own template with `let g:go_template_file = \"foo.go\"` and putting the file under the `templates/` folder. [[GH-918]](https://github.com/fatih/vim-go/pull/918)\n* Added new toggle commands to enable/disable feature that run for your\n  automatic. For example if you have `let g:go_auto_type_info = 1` enabled, you\n  can now easily enable/disable it on the fly. Support added with the following\n  commands: `:GoAutoTypeInfoToggle`, `:GoFmtAutoSaveToggle`,\n  `:GoAsmFmtAutoSaveToggle`, `:GoMetalinterAutoSaveToggle`,\n  `:GoTemplateAutoCreateToggle` [[GH-945]](https://github.com/fatih/vim-go/pull/945)\n\n\nIMPROVEMENTS:\n* `:GoDoc` accepts arguments now which are passed directly to `godoc`. So usages like `:GoDoc flag` works again (it was changed in previous versions [[GH-894]](https://github.com/fatih/vim-go/pull/894)\n* `:GoDef` works now for modified files as well [[GH-910]](https://github.com/fatih/vim-go/pull/910)\n* Internal: pass filename to the `--srcdir` flag to enable upcoming `goimports` features [[GH-957]](https://github.com/fatih/vim-go/pull/957)\n* Internal: fix indentations on all files to **2-spaces/no tabs**. This is now the default vim-go style across all VimL files [[GH-915]](https://github.com/fatih/vim-go/pull/915)\n* Internal: autocmd settings can be now dynamically enabled/disabled [[GH-939]](https://github.com/fatih/vim-go/pull/939)\n* Internal: automatically detect `GOPATH`  for :GoInstall [[GH-980]](https://github.com/fatih/vim-go/pull/980)\n* Internal: shell executions uses now by default `sh` and then resets it back to the user preference. [[GH-967]](https://github.com/fatih/vim-go/pull/967)\n* Syntax: improved syntax highglighting performance for methods, fields, structs and interface type declarations [[GH-917]](https://github.com/fatih/vim-go/pull/917)\n* Syntax: moved `:GoCoverage` highlight definition into go's syntax file for more customizability [[GH-962]](https://github.com/fatih/vim-go/pull/962)\n\n\nBUG FIXES:\n\n* Escape `#` characters when opening URL's, as it's handled as alternative file in vim [[GH-895]](https://github.com/fatih/vim-go/pull/895)\n* Fix typos in `doc/vim-go.txt` about usages of syntax highglightings [[GH-897]](https://github.com/fatih/vim-go/pull/897)\n* Fix `:GoCoverage` not running for Neovim [[GH-899]](https://github.com/fatih/vim-go/pull/899)\n* Fix `:GoFmt` not picking up `-srcdir` if the command was set to use `goimports` [[GH-904]](https://github.com/fatih/vim-go/pull/904)\n* Fix `:GoTestCompile` to not leave behind artifacts if the cwd and the test files's directory do not match [[GH-909]](https://github.com/fatih/vim-go/pull/909)\n* Fix `:GoDocBrowser` to not fail if godoc doesn't exist [[GH-920]](https://github.com/fatih/vim-go/pull/920)\n* Fix `:GoFmt` to not change the permissions of saved file. Now original file permissions are restored [[GH-922]](https://github.com/fatih/vim-go/pull/922)\n\nBACKWARDS INCOMPATIBILITIES:\n\n* `g:go_highlight_structs` and `g:go_highlight_interface` are removed in favor of `g:go_highlight_types` [[GH-917]](https://github.com/fatih/vim-go/pull/917)\n\n\n## 1.7.1 (June 7, 2016)\n\nBUG FIXES:\n* Fixed typo in `syntax/go.vim` file from `go:go_highlight_fields` to `g:go_highlight_fields`\n\n## 1.7 (June 7, 2016)\n\nFEATURES:\n\n* New **`:GoImpl`** command that generates method stubs for implementing an interface. Checkout the [demo](https://twitter.com/fatih/status/729991365581545472) to see how it works. [[GH-846]](https://github.com/fatih/vim-go/pull/846)\n* `godef` support is added back as an optional setting.  By default `:GoDef` still uses `guru`, but can be changed to `godef` by adding the option: `let g:go_def_mode = 'godef'` [[GH-888]](https://github.com/fatih/vim-go/pull/888)\n* New `<C-w><C-]>` and `<C-w>]>` shortcuts to split current window and jumpt to the identifier under cursor. [[GH-838]](https://github.com/fatih/vim-go/pull/838)\n* New syntax setting\" `g:go_highlight_fields` that highlights struct field references [[GH-854]](https://github.com/fatih/vim-go/pull/854)\n\nIMPROVEMENTS:\n\n* Invoking `:GoRename` now reloads all files to reflect new changes automatically [[GH-855]](https://github.com/fatih/vim-go/pull/855)\n* Calling `:GoTestCompile` does not create any temporary binary file anymore [[GH-879]](https://github.com/fatih/vim-go/pull/879)\n* Enable passing the `-tags` flag to `:GoDef`. Now you can pass build tags to `:GoDef` via `:GoGuruTags` or `g:go_guru_tags`\n* Internal refactoring to use custom `system()` function that wraps both the standard `system()` call and `vimproc`. Now all system calls will take advantage and will use `vimproc` if installed. [[GH-801]](https://github.com/fatih/vim-go/pull/801)\n* Completion enables now `gocode`'s `autobuild` and `propose-builtins` flags automatically. With these settings packages will be automatically build to get the freshest completion candidates and builtin keywords will be showed as well. By defaults these settings are enabled. Settings can be disabled/enabled via `g:go_gocode_autobuild` and `g:go_gocode_propose_builtins`. [[GH-815]](https://github.com/fatih/vim-go/pull/815)\n* Added new `http.HandlerFunc` snippets with `hf` and `hhf` shortcuts [[GH-816]](https://github.com/fatih/vim-go/pull/816)\n* Added new `Example` and `Benchmark` snippets with `example` and `benchmark` shortcuts [[GH-836]](https://github.com/fatih/vim-go/pull/836)\n* Search tool binaries first in `GOBIN` and then in `PATH` as most of vim-go users installs it to `GOBIN` mostly [[GH-823]](https://github.com/fatih/vim-go/pull/823)\n* Improve `guru` based commands by providing automatically detected GOPATHS, such as `gb`, `godep` to be used if possible [[GH-861]](https://github.com/fatih/vim-go/pull/861)\n* Add `<Plug>(go-imports)` mapping to make it assignable to other keys [[GH-878]](https://github.com/fatih/vim-go/pull/878)\n* Increase compatibility with tcsh [[GH-869]](https://github.com/fatih/vim-go/pull/869)\n* Improve `:GoInstallBinaries` for GOPATH's which don't have packages that work well with `go get -u`. We have a new `g:go_get_update` setting to disable it. By default it's enabled. [[GH-883]](https://github.com/fatih/vim-go/pull/883)\n\n\n\nBUG FIXES:\n* Fix `(go-freevars)` plug mapping to work as in visual mode instead of noncompatible normal mode [[GH-832]](https://github.com/fatih/vim-go/pull/832)\n* Commands based on guru now shows a more meaningful error message instead of just showing the exit status (-1)\n* Fix `:GoCoverage` accidentally enabling syntax highlighting for users who don't use syntax (i.e syntax off) [[GH-827]](https://github.com/fatih/vim-go/pull/827)\n* Fix `:GoCoverage` colors to work for xterm as well [[GH-863]](https://github.com/fatih/vim-go/pull/863)\n* Fix commenting out block of texts for Go templates (filetype gothtmltmpl) [[GH-813]](https://github.com/fatih/vim-go/pull/813)\n* Fix `:GoImplements` failing because of an empty scope definition. Now we default to current package to make it usable.\n* Fix `:GoPlay` posting to non HTTPS url. [[GH-847]](https://github.com/fatih/vim-go/pull/847)\n* Fix escaping the filenames for lint and motion commands [[GH-862]](https://github.com/fatih/vim-go/pull/862)\n* Fix escaping the filename to `:GoDef` completely for tcsh [[GH-868]](https://github.com/fatih/vim-go/pull/868)\n* Fix showing SUCCESS for `go test` related commands if no test files are available [[GH-859]](https://github.com/fatih/vim-go/pull/859)\n\n\n\n## 1.6 (April 25, 2016)\n\nFEATURES:\n\n* New `CHANGELOG.md` file (which you're reading now). This will make it easier\n  for me to track changes and release versions\n* **`:GoCoverage`** is now highlighting the current source file for\n  covered/uncovered lines. If called again it runs the tests and updates the\n  annotation. Use `:GoCoverageClear` to clear the coverage annotation.\n  This is a pretty good addition to vim-go and I suggest to check out the gif\n  that shows it in action: https://twitter.com/fatih/status/716722650383564800\n  [[GH-786]](https://github.com/fatih/vim-go/pull/786)\n* **`:GoCoverageToggle`** just like `:GoCoverage` but acts as a toggle. If run\n  again it clears the annotation.\n* **`:GoCoverageBrowser`** opens a new annotated HTML page. This is the old\n  `:GoCoverage` behavior [[GH-786]](https://github.com/fatih/vim-go/pull/786)\n* **`:GoDoc`** uses now [gogetdoc](https://github.com/zmb3/gogetdoc) to\n  lookup and display the comment documentation for the identifier under the\n  cursor. This is more superior as it support looking up dot imports, named\n  imports and imports where package name and file name are different [[GH-782]](https://github.com/fatih/vim-go/pull/782)\n* **`guru support`**: `oracle` is replaced by the new tool `guru`. `oracle.vim`\n  is therefore renamed to `guru.vim`. I've also refactored the code to make it\n  much more easier to maintain and add additional features in future (such as\n  upcoming JSON decoding). vim-go is now fully compatible with `guru`. Please\n  be sure you have installed `guru`. You can easily do it with\n  `:GoInstallBinaries`.\n* **`:GoDef`** uses now `guru definition` under the hood instead of `godef`.\n  This fixes the following issues: 1. dot imports 2. vendor imports 3. folder\n  != package name imports. The tool `godef` is also deprecated and not used\n  anymore.\n* **`:GoDef`** does have now history of the call stack. This means you can\n  easily jump back to your last entry. This can be done with the new command\n  `:GoDefPop` or the mapping `CTRL-t`. To see the stack and jump between entries\n  you can use the new command `:GoDefStack`, which shows the list of all stack\n  entries. To reset the stack list anytime you can call `:GoDefStackClear`\n  [[GH-776]](https://github.com/fatih/vim-go/pull/776)\n\nIMPROVEMENTS:\n\n* **`:GoCoverage`** is executed asynchronously when used within Neovim [[GH-686]](https://github.com/fatih/vim-go/pull/686)\n* **`:GoTestFunc`** supports now testable examples [[GH-794]](https://github.com/fatih/vim-go/pull/794)\n* **`:GoDef`** can jump to existing buffers instead of opening a new window\n  (split, vsplit or tab). By default it's disabled to not break the old\n  behavior, can be enabled with `let g:go_def_reuse_buffer = 1`\n\nBUG FIXES:\n\n* Fix not showing documentation for dot, named and package/file name being different imports [[GH-332]](https://github.com/fatih/vim-go/pull/332)\n* Term mode: fix closing location list if result is successful after a failed attempt [[GH-768]](https://github.com/fatih/vim-go/pull/768)\n* Syntax: fix gotexttmpl identifier highlighting [[GH-778]](https://github.com/fatih/vim-go/pull/778)\n* Doc: fix wrong wording for `go-run` mapping. It's for the whole main package,\n  not for the current file\n\nBACKWARDS INCOMPATIBILITIES:\n\n* `:GoDef` doesn't accept any identifier as an argument. This is not suported\n  via `guru definition` and also was not widely used either. Also with this, we\n  significantly simplified the existing def.vim code\n* `:GoOracleScope`  and `:GoOracleTags` are deprecated in favor of\n  `:GoGuruScope` and `:GoGuruTags`. Also `g:go_oracle_scope` is renamed to\n  `g:go_guru_scope`\n* `g:go_guru_scope` accepts a variable in type of `list` instead of `string`.\n  i.g: `let g:go_guru_scope = [\"github.com/fatih/structs\", \"golang.org/x/tools/...\"]`\n\n\n## 1.5 (Mar 16, 2016)\n\nFEATURES:\n* Introducing code name \"motion\". A new whole way of moving\n  around and navigating [[GH-765]](https://github.com/fatih/vim-go/pull/765). Checkout the following new changes:\n  * A vim-go specific tool, called [motion](https://github.com/fatih/motion) is being developed which\n    provides us the underlying foundation for the following and upcoming\n    new features.\n  * `]]` and `[[` motions can be used to jump between functions\n  * `if` and `af` are improved and implement from scratch. It has now\n    support for literal functions, comments of functions, better cursor\n    position support and more stable.\n  * New `:GoDecls` and `:GoDeclsDir` commands that are available if\n    `ctrlp.vim` is installed. Once called one can easily jump to any generic declaration available.\n  * I wrote two blog posts about these new features in more detail. I recommend you to read it: [Treating Go types as objects in Vim](https://medium.com/@farslan/treating-go-types-as-objects-in-vim-ed6b3fad9287#.mbwaisevp) and [Navigation between functions and types in vim-go](https://medium.com/@farslan/navigation-between-functions-and-types-in-vim-go-f9dd7de8ca37#.2sdf8tbbe)\n* A new `:GoAlternate` command that toggles to the test\n  file of the current file. It also has new appropriate mappings to open the\n  alternate file in split or tabs. [[GH-704]](https://github.com/fatih/vim-go/pull/704)\n* Now commands can choose whether they want to open a\n  `quickfix` or a `location list` via the setting `g:go_list_type`. Also all\n  the commands have now some sensible settings, some will open a qf window,\n  some will open a location list [[GH-700]](https://github.com/fatih/vim-go/pull/700)\n\nIMPROVEMENTS:\n\n* Add support for goimport's new `-srcdir`. Goimports now succesfully suports `vendor/` folders with this release. [[GH-735]](https://github.com/fatih/vim-go/pull/735)\n* Add `g:go_gorename_prefill` setting which disabled pre filling the argument for `:GoRename` [[GH-711]](https://github.com/fatih/vim-go/pull/711)\n* Improve `:GoRun` to complete to filenames [[GH-742]](https://github.com/fatih/vim-go/pull/742)\n* Highlight `//go:generate` comment directives [[GH-757]](https://github.com/fatih/vim-go/pull/757)\n* Indent code in Go HTML templates [[GH-709]](https://github.com/fatih/vim-go/pull/709)\n* Improve negative numbers of all types, octals, imaginary numbers with exponents [[GH-752]](https://github.com/fatih/vim-go/pull/752)\n* Improved internal usage of retrieving offsets [[GH-762]](https://github.com/fatih/vim-go/pull/762)\n* Improve by substitute all backslashes to slashes for filename [[GH-703]](https://github.com/fatih/vim-go/pull/703)\n* Improve internal Go package path function [[GH-702]](https://github.com/fatih/vim-go/pull/702)\n* Improved typo and grammar errors in docs [[GH-714]](https://github.com/fatih/vim-go/pull/714)\n* Improved internal `:GoInfo` automatic call [[GH-759]](https://github.com/fatih/vim-go/pull/759)\n\nBUG FIXES:\n\n* Fix oracle scope not working if trailing slash exists in scope [[GH-751]](https://github.com/fatih/vim-go/pull/751)\n* Fix `:GoErrCheck` checking abspath [[GH-671]](https://github.com/fatih/vim-go/pull/671)\n* Fix `:GoInstall` correctly parsing errors [[GH-692]](https://github.com/fatih/vim-go/pull/692)\n* Fix `:GoInstall` correctly parsing errors [[GH-692]](https://github.com/fatih/vim-go/pull/692)\n* Fix `:GoTestFunc` for neovim [[GH-695]](https://github.com/fatih/vim-go/pull/695)\n* Fix `:GoRun` accepting arguments for neovim [[GH-730]](https://github.com/fatih/vim-go/pull/730)\n* Fix `go run` mappings not working [[GH-542]](https://github.com/fatih/vim-go/pull/542)\n* Fix autodetect gopath picking up non existing GB vendor folder\n* Fix gofmt errors showing per buffer instead of per script [[GH-721]](https://github.com/fatih/vim-go/pull/721)\n* Fix some of the neosnippet snippets\n\n## 1.4 (Jan 18, 2016)\n\nFEATURES:\n\n* You waited for it for a long time. And here you have it: **Neovim support!**\n  This is a huge feature. It's fully compatible with Vim and kicks only in if\n  vim-go is being used within Neovim. Checkout the full list of changes\n  [[GH-607]](https://github.com/fatih/vim-go/pull/607):\n  * An async launcher and base foundation was implemented for the `go` command.\n  This will be used in the future for all upcoming subcommands of the `go`\n  tool.\n  * `:GoBuild` is now called asynchronously (it doesn't block the UI anymore).\n  * A new `go#jobcontrol#Statusline()` can be used to plug into the statusline.\n  This will show the status of the job running asynchronously. The statusline\n  is improved to show the status per package instead of file. Assume you have\n  three files open, all belonging to the same package, if the package build\n  (`:GoBuild`) is successful, all statusline's will be empty (means SUCCESS),\n  if it fails all files statusline's will show `FAILED`.\n  * `:GoRun` opens a new vertical terminal emulator inside Neovim and runs the\n  command there. The terminal mode can be changed with `g:go_term_mode`,\n  which is by default `vsplit`. Current options are `vsplit, split or tab`.\n  We also have three new mappings to open `:GoRun` command in different\n  terminal split modes: `<Plug>(go-run-vertical)`,  `<Plug>(go-run-split)`\n  and  `<Plug>(go-run-tab)`\n  * `:GoTest`, `:GoTestFunc` and `:GoTestCompile` opens and runs in a new\n  terminal. The view mode (split,vertical, tab) is defined with\n  `g:go_term_mode`.  The `g:go_term_enabled` setting can be use to change the\n  behavior of `:GoTestXXX` commands .If set to `1`, it opens the test\n  commands inside a terminal, if not it runs them in background just like\n  `:GoBuild` and displays the result in the statusline.\n  * We have two settings for terminal sizes: `g:go_term_height` and\n  `g:go_term_width`. By default a vertical or horizontal view is equally\n  splitted by vim automatically. However with these settings we can for\n  example have a terminal with a smaller height when we split it\n  horizontally.\n  * If a command inside the term fails (such as `go run`, `go test` ...) we\n  parse now the errors and list them inside a location list.\n* Instead of quickfix window, vim-go now uses the `location list` feature of\n  Vim. These are associated with each window independently of each other. This\n  enables us to have multiple, independent location lists per window (example\n  usages: `:GoBuild` with errors that needs to be fixed, `:GoLint` with\n  warnings that we want to check, `:GoReferrers` with a list of referred\n  identifiers) [[GH-626]](https://github.com/fatih/vim-go/pull/626)\n* a new **`:AsmFmt`** command which is integrated to work with [asmfmt](https://github.com/klauspost/asmfmt) [[GH-673]](https://github.com/fatih/vim-go/pull/673)\n* the full identifier information of a completed identifier is echoed in\n  statusline. This is very useful to see a function signatures arguments.\n  [[GH-685]](https://github.com/fatih/vim-go/pull/685)\n\nIMPROVEMENTS:\n\n* Improve `:GoFmt` by checking if the binary is indeed installed on the system [[GH-617]](https://github.com/fatih/vim-go/pull/617)\n* Improve `:GoMetaLinter` by adding the option to run the metalinter on save\n  and adding the option to limit the output to the currently active buffer. Set\n  `let g:go_metalinter_autosave = 1` to enable autosave and use `let\n  g:go_metalinter_autosave_enabled = ['vet', 'golint']` to change your options.\n  [[GH-631]](https://github.com/fatih/vim-go/pull/631)\n* Improved `:GoDef`. If `vimproc` is installed `godef` will make use of it [[GH-670]](https://github.com/fatih/vim-go/pull/670)\n* Improve completion of godoce when vimproc is used [[GH-620]](https://github.com/fatih/vim-go/pull/620)\n* Improve internal error matching prodecure to not match false positives [[GH-618]](https://github.com/fatih/vim-go/pull/618)\n* A new option to highlight interface variables with `go_highlight_interfaces` [[GH-681]](https://github.com/fatih/vim-go/pull/681)\n\nBUG FIXES\n\n* Fix `:GoFmt` changing the fileformat of the current buffer [[GH-615]](https://github.com/fatih/vim-go/pull/615)\n* Fix `:GoRename` to output the original error if parsing fails [[GH-675]](https://github.com/fatih/vim-go/pull/675)\n* Fix `:GoTest` to output the original error if parsing fails [[GH-676]](https://github.com/fatih/vim-go/pull/676)\n* Fixed `fmt.Fprintln` not to highlight as builtin [[GH-628]](https://github.com/fatih/vim-go/pull/628)\n* Fixed wrong highlighting of channels of channels [[GH-678]](https://github.com/fatih/vim-go/pull/678)\n\n## 1.3 (Nov 22, 2015)\n\nFEATURES:\n\n* A new `:GoOracleTags` command was added to pass build tags to Oracle's `-tags` flag. [[GH-573]](https://github.com/fatih/vim-go/pull/573)\n\nIMPROVEMENTS:\n\n* Change `:GoTest` command to timeout after 10 seconds. Vim UI is blocking and\n  tests with large running times makes Vim blocking for a long time. This is\n  also customizable with the new option `g:go_test_timeout`. [[GH-578]](https://github.com/fatih/vim-go/pull/578)\n* Improve `:GoRename` to collect and populate quickfix window with errors.\n  [[GH-577]](https://github.com/fatih/vim-go/pull/577)\n* Improve `:GoRun` by dropping bad filenames from quickfix window. This allows\n  us to have only valid entries which can be jumped to [[GH-547]](https://github.com/fatih/vim-go/pull/547)\n* Improve `:GoMetaLinter` quickfix output by using absolute paths. This enables\n  us to jump to errors for all cases. [[GH-565]](https://github.com/fatih/vim-go/pull/565)\n* Improve `:GoMetaLinter` command by adding a new option\n  `g:go_metalinter_deadline` which cancels the linters after 5 seconds\n  (previous default).  [[GH-576]](https://github.com/fatih/vim-go/pull/576)\n* Improve `:GoMetaLinter` by jumping to the first encountered error from the quickfix window.\n* Automatically resize quickfix window based on the number of errors [[GH-602]](https://github.com/fatih/vim-go/pull/602)\n* Improve build constraints to show invalid cases (such as `// +buildfoo`, not\n  having an empty line between the package statement, etc..). Also add missing\n  `GOARCH` values sucha s `arm64`. There are many other useful improvements,\n  for more detail please have a look at\n  [[GH-589]](https://github.com/fatih/vim-go/pull/589)\n* Add support for all values of `GOARCH` [[GH-601]](https://github.com/fatih/vim-go/pull/601)\n* Add note about Syntastic usage as this problem comes up a lot [[GH-580]](https://github.com/fatih/vim-go/pull/580)\n* Add note about `:GoUpdateBinaries` [[GH-606]](https://github.com/fatih/vim-go/pull/606)\n\nBUG FIXES:\n\n* Fixed `:GoErrCheck` showing the correct output when executed inside the source folder [[GH-564]](https://github.com/fatih/vim-go/pull/564)\n* Fixed `:GoBuild` by not using `/dev/null` anymore for build output (not\n  supported by `go`). We pass a temporary file now. [[GH-567]](https://github.com/fatih/vim-go/pull/567)\n* Fixed `:GoFmt` passing `g:go_fmt_options` options to `goimports`. This option\n  is only valid with `gofmt`. [[GH-590]](https://github.com/fatih/vim-go/pull/590)\n* Fix vim-go for `cygwin` users. [[GH-575]](https://github.com/fatih/vim-go/pull/575)\n* Fixed identifier in template files to be highlighted correctly [[GH-559]](https://github.com/fatih/vim-go/pull/559)\n* Fixed character region in template files to be highlighted correctly [[GH-603]](https://github.com/fatih/vim-go/pull/603)\n* Fixed variables in template files to be highlighted correctly [[GH-611]](https://github.com/fatih/vim-go/pull/611)\n* Do not treat builtins as keywords. Now `make` will not highlighted but\n  `make()` will be highlighted (gh-605)\n\n## 1.2 (Oct 2, 2015)\n\nFEATURES:\n\n* A new `:GoMetaLinter` command which invokes [gometalinter](https://github.com/alecthomas/gometalinter). Please check the PR [[GH-553]](https://github.com/fatih/vim-go/pull/553) for more detail on customizing and usage of `:GoMetaLinter`.\n\nIMPROVEMENTS:\n\n* Improve `:GoImport` to trim spaces when including import paths of form `\"fmt \"`\n* Avoid setting `filetype` twice. Previously it was doing it twice, which was expensive\n* Improve handling of GOPATH's with trailing `/` characters, such as `/home/user/go/`\n* Add a new `g:go_highlight_string_spellcheck` feature, which is enabled by feature. Now if spell is enabled, go strings are also checked.\n* Specify our limited but functional [gb](http://getgb.io/) support\n\nBUG FIXES:\n* Fixed `:GoRun` to display errors when `g:go_dispatch_enabled` was enabled\n* Fixed `:GoDrop` displaying \"Not enough arguments\" (regression)\n* Fixed `:GoErrCheck` not showing `PASS` message if the command was successful\n* Fixed `:GoErrCheck` not executing in the directory of the currently edited file\n* Close quickfix window after a successful second round of `:GoInstall`\n* Fix passing files rather than packages to certain oracle commands.\n* Escape files passed to oracle command. This could lead to some serious things.\n* Clear `g:go_oracle_scope` when the scope was reseted. Previously it was set to empty string, which was causing false positives.\n* Correct various misspellings.\n\n## 1.1 (Jul 25, 2015)\n\nWith this release the version will now increase in `minor` levels. So the next\nrelease will be `1.2`, the other one `1.3`, etc.. This provides us more\nflexibility (like releasing patch versions if needed).\n\nFEATURES:\n* A new `:GoGenerate` command is now available which can be used to invoke `go generate` within vim\n* Vim-go didn't had any license, now we use BSD 3-Clause License (the same as Go). This is needed for Linux distributions to package vim-go and is also something that people asked for.\n\nIMPROVEMENTS:\n* Improve commands `GoRun, GoTest{,Func,Compile}, GoCoverage,\n  GoGenerate, GoErrcheck, GoLint, and GoVet` to handle multiple arguments.\n  Previously this feature was limited to only certain commands. What this means\n  is, for example `:GoVet . -all` will invoke `go tool vet . -all`\n  automatically instead of plan `go vet`. This is one of the big changes in\n  this release, so give it a try :)\n* Improved `:GoFmt` command, which now uses the `-w` flag to\n  write to the source code directly, instead of outputting it to stdout. This\n  makes `:GoFmt` much more faster than the current implementation. This is one\n  of the big changes in this release, so feedback is welcome!\n* Improve `:GoImport` to have a `!` feature. Now when when called\n  with a `!` appended it will go get it. i.e: `:GoImport!\n  github.com/fatih/color`. Useful if `:GoImport` fails and you want to download\n  it.\n* Automatic GOPATH detections can now detect `gb` vendored folders. Some commands should now work without any problem when invoked on a `gb` project.\n* All command arguments are now properly escaped for shell invocation.\n* Added the `-f` flag to :GoInstallBinaries command to support `git url.<base>.insteadOf` configuration\n* Improve width and precision highlighting, such as `%s %5s %-5s %5.5f %.5f`\n* Show an error if a region is not selected when `:GoFreeVars` is called\n\nBUG FIXES:\n* Fix`:GoDef` for files containing spaces. We know escape the files before passing to `:GoDef`\n* Fix `:GoFmt` not picking up the correct GOPATH when the fmt command was set to `goimports`\n* Fix and simplify README.md, add Wiki reference\n* Fixed tagbar integration to show correct imports.\n\n\n## 1.0.5 (May 26, 2015)\n\nFEATURES:\n* A new `:GoOracleScope` is added to change the oracle scope on-the-fly. It\n  accepts import paths as arguments. If no arguments are passed it prints the\n  current custom oracle scope. `:GoOracleScope` also supports completion of\n  import paths, so it's very fast and handy to use. `:GoOracleScope \"\"` clears\n  the current custom scope.\n* A new `:GoPath` command that displays the current `GOPATH`. A path can be\n  passed to change the `GOPATH` (i.e `:GoPath ~/foo/src`). `:GoPath \"\"` clears\n  and resets the `GOPATH` to the initial value.\n* A new \"autodetect GOPATH\" feature is added. This automatically detects if the\n  project is using `godep` or is under a `src` root directory which is not in\n  `GOPATH` and changes/modifies the `GOPATH` so all commands work based on this\n  GOPATH. What this means is, commands such as `:GoDef`, `:GoBuild`, etc.. will\n  include the Godeps folder. For example any go-to-definition via `:GoDef` will\n  jump to the source code inside Godeps. This is enabled by default, but can\n  disabled with `let g:go_autodetect_gopath = 0`. This new feature is also the\n  foundation for other tools such as `gb` or `wgo`.\n\nIMPROVEMENTS:\n* Improve `:GoFmt` (gofmt and goimports) speed. Now it's 2x faster than the previous implementation.\n* Add Dispatch support for `:GoBuild` and `:GoRun`. For more info about\n  dispatch see https://github.com/tpope/vim-dispatch . By default it's\n  disabled, to enable it add `let g:go_dispatch_enabled = 1` to your vimrc.\n* Add support for the bang `!` attribute for all `go` tool commands. What this\n  does it, if `:GoBuild` is called it will jump to the error. But `:GoBuild!`\n  will not jump to any error. This has the same behavior as the internal\n  `:make` command in vim. We had this feature already for `:GoBuild` and\n  `:GoRun`. But not for `:GoInstall`, `:GoTest`, etc.. Now all commands are\n  unified.\n* Add autojump to error for `:GoInstall`.\n* Add autowrite feature for `:GoInstall`, `:GoTestXXX` functions and `:GoVet`\n* Support `git url.<base>.insteadOf` and custom import paths of binaries. This\n  improves the commands `:GoInstallBinaries` and `:GoUpdateBinaries`.\n* Add support for highlighting go templates with `*.tmpl` extensions. Based on\n  the work from @cespare from https://github.com/cespare/vim-go-templates\n\nBUG FIXES:\n* Fix clearing the status bar when `:GoErrCheck` is called\n* Fix godocNotFound to not match 'os' pkg contents. This improves the command\n  `:GoDoc`\n* Fix parsing and jumping to error locations when used Vim from a different\n  directory than the current buffer's directory\n* Fix completion showing duplicates paths for completion results, such as\n  github.com/fatih/color and github.com/fatih/color/.\n\n## 1.0.4 (Apr 28, 2015)\n\nFEATURES:\n\n* A new `:GoTestFunc` command (with appropriate\n  mappings) is added. Run tests function which surrounds the current cursor\n  location. Useful to test single tests.\n* Highlight all Go operators. Previously not all\n  operators were highlighted. As previously, to highlight options, enable it\n  with by setting `g:go_highlight_operators` to 1 in your vimrc.\n\nIMPROVEMENTS:\n\n* Improved certain `:GoDoc` usages to show a better error message\n* Improved `:GoRename` to have a default value for rename input. Avoids retyping similar words.\n* Synced with latest Oracle version. `callgraph` is removed.\n* Removed our custom referrers mode. New version of oracle now displays the matching lines.\n\nBUG FIXES:\n\n* Fixed the internal `executeInDir` function which was failing when ignorelist was not set properly.\n* Fixed trailing slash for package completion with `:GoImport`\n* Fixed paths in error list for Windows users.\n* Fixed not showing \"import cycle not allowed\" error message when called `:GoBuild` or `:GoRun`\n* Fixed users using vimproc requiring arguments to functions to be escaped.\n* Fixed depth for test snippets\n* Fixed neosnippet support loading snippet files the second time if necessary.\n\n## 1.0.3 (Mar 7, 2015)\n\nFEATURES:\n* A new `:GoTestCompile` command (with appropriate mappings) is added. Useful to compile a test binary or show/fix compile errors in quickfix window\n\nIMPROVEMENTS:\n* `referrer` mode is improved to show referring lines in the quickfix window\n* A new `errt` snippet is added, which expands to `if err != nil { t.Fatal(err) }`\n* A new `errh` snippet is added, useful to be used in a `http.Handler`\n* UltiSnips snippets are improved to take advance of Vim's `Visual` mode. For example selecting a block and typing `if` will create an if scope around the block.\n* Cleanup README.md\n\nBUG FIXES:\n* Fix trimming brackets if completion was invoked on a previous completion\n* Fix Oracle scope settings. Added docs about usage.\n* Fixed previously broken `var` and `vars` snippets\n* Fix duplicate docs\n* Fix fallback binary path for Windows users. The fallback mechanism is used to discover the necessary Go tools, such as `godef`, `gocode`, etc...\n\n## 1.0.2 (Feb 17, 2015)\n\nFEATURES:\n\n* New snippets are added, mostly for testing ( [changes](https://github.com/fatih/vim-go/pull/321/files))\n\nIMPROVEMENTS:\n\n* Enable all Oracle commands. Docs, mappings and commands are also added. It uses Quickfix list instead of a custom UI.\n* Clarify installation process in Readme, add instructions for vim-plug, NeoBundle and manual.\n\nBUG FIXES:\n\n* Fix shiftwidth parsing, it was broken in the previous release for old Vim versions\n* Fix experimantal mode\n\n\n## 1.0.1 (Feb 9, 2015)\n\nFEATURES:\n\n* New feature to highlight build constraints (disabled by default)\n\nIMPROVEMENTS:\n\n* Updated godef import path\n* Updated Readme for possible problems with `csh`\n* Documentation for text objects are updated, typo fixes are merged\n* If vimproc is installed, Windows users will use it for autocompletion\n* Improve UltiSnips snippets to pick Visual selection (demo: http://quick.as/0dvigz5)\n* Packages with extensions, like \"gopkg.in/yaml.v2\" can be now displayed\n* Packages with different import paths, like \"github.com/bitly/go-simplejson\" can be now displayed\n\nBUG FIXES:\n\n* Fatal errors are now parsed successfully and populated to quickfix list\n* Shiftwidth is changed to use shiftwidth() function. Fixes usage with plugins like vim-sleuth and possible mis usage (like setting shiftwidth to zero)\n* Added a new [Donation](https://github.com/fatih/vim-go#donations) section to Readme, for those who ask for it.\n* Fix parsing of errcheck error syntax\n* Fix consistency between Neosnippet and UltiSnips snippets\n\n\n## 1.0 (Dec 24, 2014)\n\nWe don't tag any changes or releases, so let's start with `1.0`. Our Windows\nsupport is now in a good shape, tons of bugs are fixed, many new features and\nimprovements is being added and it's getting better with each day (thanks to\nthe community contributions).\n\n## 0.0 (Mar 24, 2014)\n\nInitial commit: https://github.com/fatih/vim-go/commit/78c5caa82c111c50e9c219f222d65b07694f8f5a\n\n<!--\n vim: et ts=2 sw=2\n-->\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM --platform=linux/amd64 golang:1.26.0\n\nRUN apt-get update -y --allow-insecure-repositories && \\\n  apt-get install -y build-essential curl git libncurses5-dev python3-pip && \\\n  apt-get clean && \\\n  rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*\n\nRUN pip3 install vim-vint --break-system-packages\n\nRUN useradd -ms /bin/bash -d /vim-go vim-go\nUSER vim-go\n\nCOPY scripts/install-vim /vim-go/scripts/install-vim\nWORKDIR /vim-go\n\nRUN scripts/install-vim vim-8.2\nRUN scripts/install-vim vim-9.1\nRUN scripts/install-vim nvim\n\nCOPY . /vim-go/\nWORKDIR /vim-go\n\nRUN scripts/install-tools vim-8.2\nRUN scripts/install-tools vim-9.1\nRUN scripts/install-tools nvim\n\nENTRYPOINT [\"make\"]\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2015, 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 vim-go 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"
  },
  {
    "path": "Makefile",
    "content": "VIMS ?= vim-8.2 vim-9.1 nvim\nTEST_FLAGS ?=\n\nall: install lint test\n\ninstall:\n\t@echo \"==> Installing Vims: $(VIMS)\"\n\t@for vim in $(VIMS); do \\\n\t\t./scripts/install-vim $$vim; \\\n\t\t./scripts/install-tools $$vim; \\\n\tdone\n\ntest:\n\t@echo \"==> Running tests for $(VIMS)\"\n\t@for vim in $(VIMS); do \\\n\t\t./scripts/test $(TEST_FLAGS) $$vim; \\\n\tdone\n\nlint:\n\t@echo \"==> Running linting tools\"\n\t@./scripts/lint vim-9.1\n\ndocker:\n\t@echo \"==> Building/starting Docker container\"\n\t@./scripts/docker-test\n\nclean:\n\t@echo \"==> Cleaning /tmp/vim-go-test\"\n\t@rm -rf /tmp/vim-go-test\n\n.PHONY: all test install clean lint docker\n"
  },
  {
    "path": "README.md",
    "content": "# vim-go [![GitHub Actions Status](https://github.com/fatih/vim-go/workflows/test/badge.svg)](https://github.com/fatih/vim-go/actions)\n\n\n\n<p align=\"center\">\n  <img style=\"float: right;\" src=\"assets/vim-go.png\" alt=\"Vim-go logo\"/>\n</p>\n\n## Features\n\nThis plugin adds Go language support for Vim, with the following main features:\n\n* Compile your package with `:GoBuild`, install it with `:GoInstall` or test it\n  with `:GoTest`. Run a single test with `:GoTestFunc`).\n* Quickly execute your current file(s) with `:GoRun`.\n* Improved syntax highlighting and folding.\n* Debug programs with integrated [`delve`](https://github.com/go-delve/delve) support with `:GoDebugStart`.\n* Completion and many other features support via `gopls`.\n* formatting on save keeps the cursor position and undo history.\n* Go to symbol/declaration with `:GoDef`.\n* Look up documentation with `:GoDoc` or `:GoDocBrowser`.\n* Easily import packages via `:GoImport`, remove them via `:GoDrop`.\n* Precise type-safe renaming of identifiers with `:GoRename`.\n* See which code is covered by tests with `:GoCoverage`.\n* Add or remove tags on struct fields with `:GoAddTags` and `:GoRemoveTags`.\n* Lint your code with `:GoLint` or `:GoMetaLinter`, run your code through `:GoVet` to catch static errors, or make sure errors are checked with `:GoErrCheck`.\n* Advanced source analysis utilizing `gopls`, such as `:GoImplements`, `:GoCallees`, and `:GoReferrers`.\n* ... and many more! Please see [doc/vim-go.txt](doc/vim-go.txt) for more information.\n* Integration with [`gopls`](https://github.com/golang/tools/blob/master/gopls/README.md).\n* The `gopls` instance can be shared with other Vim plugins.\n* Vim-go's use of `gopls` can be disabled and alternative tools can be used when desired.\n* Integration with [`Tagbar`](https://github.com/preservim/tagbar) via [`gotags`](https://github.com/jstemmer/gotags).\n* Integration with [`Ultisnips`](https://github.com/SirVer/ultisnips) and other snippet engines.\n\n## Install\n\nvim-go requires at least Vim 8.2.5072 or Neovim 0.4.0.\n\nThe [**latest stable release**](https://github.com/fatih/vim-go/releases/latest) is the\nrecommended version to use. If you choose to use the master branch instead,\nplease do so with caution; it is a _development_ branch.\n\n\nvim-go follows the standard runtime path structure. Below are some helper lines\nfor popular package managers:\n\n* [Vim 8 packages](http://vimhelp.appspot.com/repeat.txt.html#packages)\n  * `git clone https://github.com/fatih/vim-go.git ~/.vim/pack/plugins/start/vim-go`\n* [Neovim packages](https://neovim.io/doc/user/repeat.html#packages)\n  * `git clone https://github.com/fatih/vim-go.git ~/.local/share/nvim/site/pack/plugins/start/vim-go`\n* [Pathogen](https://github.com/tpope/vim-pathogen)\n  * `git clone https://github.com/fatih/vim-go.git ~/.vim/bundle/vim-go`\n* [vim-plug](https://github.com/junegunn/vim-plug)\n  * `Plug 'fatih/vim-go', { 'do': ':GoUpdateBinaries' }`\n* [Vundle](https://github.com/VundleVim/Vundle.vim)\n  * `Plugin 'fatih/vim-go'`\n\nYou will also need to install all the necessary binaries. vim-go makes it easy\nto install all of them by providing a command, `:GoInstallBinaries`, which will\n`go install` all the required binaries.\n\nCheck out the Install section in [the documentation](doc/vim-go.txt) for more\ndetailed instructions (`:help go-install`).\n\n## Usage\n\nThe full documentation can be found at [doc/vim-go.txt](doc/vim-go.txt). You can\ndisplay it from within Vim with `:help vim-go`.\n\nDepending on your installation method, you may have to generate the plugin's\n[`help tags`](http://vimhelp.appspot.com/helphelp.txt.html#%3Ahelptags)\nmanually (e.g. `:helptags ALL`).\n\nWe also have a [tutorial](https://github.com/fatih/vim-go/wiki/Tutorial) in the [official vim-go wiki](https://github.com/fatih/vim-go/wiki).\n\n## FAQ and troubleshooting\n\nThe FAQ and troubleshooting tips are in the documentation and can be quickly\naccessed using `:help go-troubleshooting`. If you believe you've found a bug or\nshortcoming in vim-go that is neither addressed by help nor in [existing\nissues](https://github.com/fatih/vim-go/issues), please open an issue with\nclear reproduction steps. `:GoReportGitHubIssue` can be used pre-populate a lot\nof the information needed when creating a new issue.\n\n## Contributing\n\nAll PRs are welcome. If you are planning to contribute a large patch or to\nintegrate a new tool, please create an issue first to get any upfront questions\nor design decisions out of the way first.\n\nYou can run the tests locally by running `make`. It will lint the VimL for you,\nlint the documentation, and run the tests against the minimum required version\nof Vim, other versions of Vim that may be critical to support, and Neovim.\n\n## License\n\nThe BSD 3-Clause License - see [`LICENSE`](LICENSE) for more details\n\n"
  },
  {
    "path": "addon-info.json",
    "content": "{\n  \"name\": \"vim-go\",\n  \"description\": \"Full featured Go (golang) support for Vim.\",\n  \"author\": \"Fatih Arslan <fatih@arslan.io>\",\n  \"repository\" : {\"type\": \"git\", \"url\": \"https://github.com/fatih/vim-go.git\"}\n}\n"
  },
  {
    "path": "autoload/ctrlp/decls.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nlet s:go_decls_var = {\n      \\  'init':   'ctrlp#decls#init()',\n      \\  'exit':   'ctrlp#decls#exit()',\n      \\  'enter':  'ctrlp#decls#enter()',\n      \\  'accept': 'ctrlp#decls#accept',\n      \\  'lname':  'declarations',\n      \\  'sname':  'decls',\n      \\  'type':   'tabs',\n      \\}\n\nif exists('g:ctrlp_ext_vars') && !empty(g:ctrlp_ext_vars)\n  let g:ctrlp_ext_vars = add(g:ctrlp_ext_vars, s:go_decls_var)\nelse\n  let g:ctrlp_ext_vars = [s:go_decls_var]\nendif\n\nfunction! ctrlp#decls#init() abort\n  cal s:enable_syntax()\n  return s:decls\nendfunction\n\nfunction! ctrlp#decls#exit() abort\n  unlet! s:decls s:target\nendfunction\n\n\" The action to perform on the selected string\n\" Arguments:\n\"  a:mode   the mode that has been chosen by pressing <cr> <c-v> <c-t> or <c-x>\n\"           the values are 'e', 'v', 't' and 'h', respectively\n\"  a:str    the selected string\nfunction! ctrlp#decls#accept(mode, str) abort\n  try\n    let vals = matchlist(a:str, '|\\(.\\{-}\\):\\(\\d\\+\\):\\(\\d\\+\\)\\s*\\(.*\\)|')\n\n    \" i.e: main.go\n    let filename =  vals[1]\n    let line =  vals[2]\n    let col =  vals[3]\n\n    \" i.e: /Users/fatih/vim-go/main.go\n    let filepath =  fnamemodify(filename, \":p\")\n\n    \" acceptile is a very versatile method,\n    call ctrlp#acceptfile(a:mode, filepath)\n    call cursor(line, col)\n    silent! norm! zvzz\n  endtry\nendfunction\n\nfunction! ctrlp#decls#enter() abort\n  let s:decls = []\n\n  let l:cmd = ['motion',\n        \\ '-format', 'vim',\n        \\ '-mode', 'decls',\n        \\ '-include', go#config#DeclsIncludes(),\n        \\ ]\n\n  call go#cmd#autowrite()\n\n  if s:mode == 0\n    \" current file mode\n    let l:fname = expand(\"%:p\")\n    if exists('s:target')\n      let l:fname = s:target\n    endif\n\n    let cmd += ['-file', l:fname]\n  else\n    \" all functions mode\n    let l:dir = expand(\"%:p:h\")\n    if exists('s:target')\n      let l:dir = s:target\n    endif\n\n    let cmd += ['-dir', l:dir]\n  endif\n\n  let [l:out, l:err] = go#util#Exec(l:cmd)\n  if l:err\n    call go#util#EchoError(l:out)\n    return\n  endif\n\n  let result = eval(out)\n  if type(result) != 4 || !has_key(result, 'decls')\n    return\n  endif\n\n  let decls = result.decls\n\n  \" find the maximum function name\n  let max_len = 0\n  for decl in decls\n    if len(decl.ident)> max_len\n      let max_len = len(decl.ident)\n    endif\n  endfor\n\n  for decl in decls\n    \" paddings\n    let space = \" \"\n    for i in range(max_len - len(decl.ident))\n      let space .= \" \"\n    endfor\n\n    call add(s:decls, printf(\"%s\\t%s |%s:%s:%s|\\t%s\",\n          \\ decl.ident . space,\n          \\ decl.keyword,\n          \\ fnamemodify(decl.filename, \":p\"),\n          \\ decl.line,\n          \\ decl.col,\n          \\ decl.full,\n          \\))\n  endfor\nendfunc\n\nfunction! s:enable_syntax() abort\n  if !(has('syntax') && exists('g:syntax_on'))\n    return\n  endif\n\n  syntax match CtrlPIdent      '\\zs\\h\\+\\ze\\s'\n  syntax match CtrlPKeyword\t\t '\\zs[^\\t|]\\+\\ze|[^|]\\+:\\d\\+:\\d\\+|'\n  syntax match CtrlPFilename   '|\\zs[^|]\\+:\\d\\+:\\d\\+\\ze|'\n  syntax match CtrlPSignature  '\\zs\\t.*\\ze$' contains=CtrlPKeyWord,CtrlPFilename\n\n  highlight link  CtrlPIdent      Function\n  highlight link  CtrlPKeyword   Keyword\n  highlight link  CtrlPFilename  SpecialComment\n  highlight link  CtrlPSignature Comment\nendfunction\n\nlet s:id = g:ctrlp_builtins + len(g:ctrlp_ext_vars)\n\nfunction! ctrlp#decls#cmd(mode, ...) abort\n  let s:mode = a:mode\n  if a:0 && !empty(a:1)\n    let s:target = a:1\n  endif\n  return s:id\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/fzf/decls.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! s:code(group, attr) abort\n  let code = synIDattr(synIDtrans(hlID(a:group)), a:attr, \"cterm\")\n  if code =~ '^[0-9]\\+$'\n    return code\n  endif\nendfunction\n\nfunction! s:color(str, group) abort\n  let fg = s:code(a:group, \"fg\")\n  let bg = s:code(a:group, \"bg\")\n  let bold = s:code(a:group, \"bold\")\n  let italic = s:code(a:group, \"italic\")\n  let reverse = s:code(a:group, \"reverse\")\n  let underline = s:code(a:group, \"underline\")\n  let color = (empty(fg) ? \"\" : (\"38;5;\".fg)) .\n            \\ (empty(bg) ? \"\" : (\";48;5;\".bg)) .\n            \\ (empty(bold) ? \"\" : \";1\") .\n            \\ (empty(italic) ? \"\" : \";3\") .\n            \\ (empty(reverse) ? \"\" : \";7\") .\n            \\ (empty(underline) ? \"\" : \";4\")\n  return printf(\"\\x1b[%sm%s\\x1b[m\", color, a:str)\nendfunction\n\nfunction! s:sink(str) abort\n  if len(a:str) < 2\n    return\n  endif\n  try\n    \" we jump to the file directory so we can get the fullpath via fnamemodify\n    \" below\n    let l:dir = go#util#Chdir(s:current_dir)\n\n    let vals = matchlist(a:str[1], '|\\(.\\{-}\\):\\(\\d\\+\\):\\(\\d\\+\\)\\s*\\(.*\\)|')\n\n    \" i.e: main.go\n    let filename =  vals[1]\n    let line =  vals[2]\n    let col =  vals[3]\n\n    \" i.e: /Users/fatih/vim-go/main.go\n    let filepath =  fnamemodify(filename, \":p\")\n\n    let cmd = get({'ctrl-x': 'split',\n          \\ 'ctrl-v': 'vertical split',\n          \\ 'ctrl-t': 'tabe'}, a:str[0], 'e')\n    execute cmd fnameescape(filepath)\n    call cursor(line, col)\n    silent! norm! zvzz\n  finally\n    \"jump back to old dir\n    call go#util#Chdir(l:dir)\n  endtry\nendfunction\n\nfunction! s:source(mode,...) abort\n  let s:current_dir = expand('%:p:h')\n  let ret_decls = []\n\n  let l:cmd = ['motion',\n        \\ '-format', 'vim',\n        \\ '-mode', 'decls',\n        \\ '-include', go#config#DeclsIncludes(),\n        \\ ]\n\n  call go#cmd#autowrite()\n\n  if a:mode == 0\n    \" current file mode\n    let l:fname = expand(\"%:p\")\n    if a:0 && !empty(a:1)\n      let l:fname = a:1\n    endif\n\n    let cmd += ['-file', l:fname]\n  else\n    \" all functions mode\n    if a:0 && !empty(a:1)\n      let s:current_dir = a:1\n    endif\n\n    let l:cmd += ['-dir', s:current_dir]\n  endif\n\n  let [l:out, l:err] = go#util#Exec(l:cmd)\n  if l:err\n    call go#util#EchoError(l:out)\n    return\n  endif\n\n  let result = eval(out)\n  if type(result) != 4 || !has_key(result, 'decls')\n    return ret_decls\n  endif\n\n  let decls = result.decls\n\n  \" find the maximum function name\n  let max_len = 0\n  for decl in decls\n    if len(decl.ident)> max_len\n      let max_len = len(decl.ident)\n    endif\n  endfor\n\n  for decl in decls\n    \" paddings\n    let space = \" \"\n    for i in range(max_len - len(decl.ident))\n      let space .= \" \"\n    endfor\n\n    let pos = printf(\"|%s:%s:%s|\",\n          \\ fnamemodify(decl.filename, \":t\"),\n          \\ decl.line,\n          \\ decl.col\n          \\)\n    call add(ret_decls, printf(\"%s\\t%s\\t%s\\t%s\",\n          \\ s:color(decl.ident . space, \"goDeclsFzfFunction\"),\n          \\ s:color(decl.keyword, \"goDeclsFzfKeyword\"),\n          \\ s:color(decl.full, \"goDeclsFzfComment\"),\n          \\ s:color(pos, \"goDeclsFzfSpecialComment\"),\n          \\))\n  endfor\n\n  return sort(ret_decls)\nendfunc\n\nfunction! fzf#decls#cmd(...) abort\n  let normal_fg = s:code(\"Normal\", \"fg\")\n  let normal_bg = s:code(\"Normal\", \"bg\")\n  let cursor_fg = s:code(\"CursorLine\", \"fg\")\n  let cursor_bg = s:code(\"CursorLine\", \"bg\")\n  let colors = printf(\" --color %s%s%s%s%s\",\n        \\ &background,\n        \\ empty(normal_fg) ? \"\" : (\",fg:\".normal_fg),\n        \\ empty(normal_bg) ? \"\" : (\",bg:\".normal_bg),\n        \\ empty(cursor_fg) ? \"\" : (\",fg+:\".cursor_fg),\n        \\ empty(cursor_bg) ? \"\" : (\",bg+:\".cursor_bg),\n        \\)\n  call fzf#run(fzf#wrap('GoDecls', {\n        \\ 'source': call('<sid>source', a:000),\n        \\ 'options': printf('-n 1 --with-nth 1,2 --delimiter=$''\\t'' --preview \"echo {3}\" --preview-window \"wrap\" --ansi --prompt \"GoDecls> \" --expect=ctrl-t,ctrl-v,ctrl-x%s', colors),\n        \\ 'sink*': function('s:sink')\n        \\ }))\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/alternate.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\n\" Test alternates between the implementation of code and the test code.\nfunction! go#alternate#Switch(bang, cmd) abort\n  let file = expand('%')\n  if empty(file)\n    call go#util#EchoError(\"no buffer name\")\n    return\n  elseif file =~# '^\\f\\+_test\\.go$'\n    let l:root = split(file, '_test.go$')[0]\n    let l:alt_file = l:root . \".go\"\n  elseif file =~# '^\\f\\+\\.go$'\n    let l:root = split(file, \".go$\")[0]\n    let l:alt_file = l:root . '_test.go'\n  else\n    call go#util#EchoError(\"not a go file\")\n    return\n  endif\n  if !filereadable(alt_file) && !bufexists(alt_file) && !a:bang\n    call go#util#EchoError(\"couldn't find \".alt_file)\n    return\n  elseif empty(a:cmd)\n    execute \":\" . go#config#AlternateMode() . \" \" . alt_file\n  else\n    execute \":\" . a:cmd . \" \" . alt_file\n  endif\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/asmfmt.vim",
    "content": "\" asmfmt.vim: Vim command to format Go asm files with asmfmt\n\" (github.com/klauspost/asmfmt).\n\"\n\" This filetype plugin adds new commands for asm buffers:\n\"\n\"   :Fmt\n\"\n\"       Filter the current asm buffer through asmfmt.\n\"       It tries to preserve cursor position and avoids\n\"       replacing the buffer with stderr output.\n\"\n\" Options:\n\"\n\"   g:go_asmfmt_autosave [default=0]\n\"\n\"       Flag to automatically call :Fmt when file is saved.\n\n\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nlet s:got_fmt_error = 0\n\n\" This is a trimmed-down version of the logic in fmt.vim.\n\nfunction! go#asmfmt#Format() abort\n  \" Save state.\n  let l:curw = winsaveview()\n\n  \" Write the current buffer to a tempfile.\n  let l:tmpname = tempname()\n  call writefile(go#util#GetLines(), l:tmpname)\n\n  \" Run asmfmt.\n  let [l:out, l:err] = go#util#Exec(['asmfmt', '-w', l:tmpname])\n  if l:err\n    call go#util#EchoError(l:out)\n    return\n  endif\n\n  \" Remove undo point caused by BufWritePre.\n  try | silent undojoin | catch | endtry\n\n  \" Replace the current file with the temp file; then reload the buffer.\n  let old_fileformat = &fileformat\n\n  \" save old file permissions\n  let original_fperm = getfperm(expand('%'))\n  call rename(l:tmpname, expand('%'))\n\n  \" restore old file permissions\n  call setfperm(expand('%'), original_fperm)\n  silent edit!\n  let &fileformat = old_fileformat\n  let &syntax = &syntax\n\n  \" Restore the cursor/window positions.\n  call winrestview(l:curw)\nendfunction\n\nfunction! go#asmfmt#ToggleAsmFmtAutoSave() abort\n  if go#config#AsmfmtAutosave()\n    call go#config#SetAsmfmtAutosave(1)\n    call go#util#EchoProgress(\"auto asmfmt enabled\")\n    return\n  end\n\n  call go#config#SetAsmfmtAutosave(0)\n  call go#util#EchoProgress(\"auto asmfmt disabled\")\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/auto.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! go#auto#template_autocreate()\n  if !go#config#TemplateAutocreate() || !&modifiable\n    return\n  endif\n\n  \" create new template from scratch\n  call go#template#create()\nendfunction\n\nfunction! go#auto#complete_done()\n  if &omnifunc isnot 'go#complete#Complete'\n    return\n  endif\n\n  call s:echo_go_info()\n  call s:ExpandSnippet()\nendfunction\n\nfunction! s:ExpandSnippet() abort\n  if !exists('v:completed_item') || empty(v:completed_item) || !go#config#GoplsUsePlaceholders()\n    return\n  endif\n\n\n  let l:engine = go#config#SnippetEngine()\n\n  if l:engine is 'ultisnips'\n    if !get(g:, 'did_plugin_ultisnips', 0)\n      return\n    endif\n    \" the snippet may have a '{\\}' in it. For UltiSnips, that should be spelled\n    \" \\{}. fmt.Printf is such a snippet that can be used to demonstrate.\n    let l:snippet = substitute(v:completed_item.word, '{\\\\}', '\\{}', 'g')\n\n    \" If there are no placeholders in the returned text, then do not expand\n    \" the snippet, because Ultisnip does not support nested snippets, and the\n    \" user may already be in an expanded snippet. While this isn't foolproof,\n    \" because there may be placeholders in the snippet, it at least solves the\n    \" simple case.\n    if stridx(l:snippet, '$') == -1\n      return\n    endif\n    call UltiSnips#Anon(l:snippet, v:completed_item.word, '', 'i')\n\"  elseif l:engine is 'neosnippet'\n\"    \" TODO(bc): make the anonymous expansion for neosnippet work\n\"\n\"    if !get(g:, 'loaded_neosnippet') is 1\n\"      return\n\"    endif\n\"\n\"    \" neosnippet#anonymous doesn't need a trigger, so replace the\n\"    \" completed_item.word with an empty string before calling neosnippet#anonymous\n\"    let l:snippet = substitute(v:completed_item.word, '{\\\\}', '\\{\\}', 'g')\n\"    call setline('.', substitute(getline('.'), substitute(v:completed_item.word, '\\', '\\\\', 'g'), '', ''))\n\"    call neosnippet#anonymous(l:snippet)\n  endif\nendfunction\n\nfunction! s:echo_go_info()\n  if !go#config#EchoGoInfo()\n    return\n  endif\n\n  if !exists('v:completed_item') || empty(v:completed_item)\n    return\n  endif\n  let item = v:completed_item\n\n  if !has_key(item, \"user_data\")\n    return\n  endif\n\n  if empty(item.user_data)\n    return\n  endif\n\n  redraws! | echo \"vim-go: \" | echohl Function | echon item.user_data | echohl None\nendfunction\n\nlet s:timer_id = 0\n\n\" go#auto#update_autocmd() will be called on BufEnter,CursorHold. This\n\" configures the augroup according to conditions below.\n\"\n\" | # | has_timer | should_enable | do                                 |\n\" |---|-----------|---------------|------------------------------------|\n\" | 1 | false     | false         | return early                       |\n\" | 2 | true      | true          | return early                       |\n\" | 3 | true      | false         | clear the group and stop the timer |\n\" | 4 | false     | true          | configure the group                |\nfunction! go#auto#update_autocmd()\n  let has_timer = get(b:, 'has_timer')\n  let should_enable = go#config#AutoTypeInfo() || go#config#AutoSameids()\n  if (!has_timer && !should_enable) || (has_timer && should_enable)\n    return\n  endif\n\n  if has_timer\n    augroup vim-go-buffer-auto\n      autocmd! * <buffer>\n    augroup END\n    let b:has_timer = 0\n    call s:timer_stop()\n    return\n  endif\n\n  augroup vim-go-buffer-auto\n    autocmd! * <buffer>\n    autocmd CursorMoved <buffer> call s:timer_restart()\n    autocmd BufLeave <buffer> call s:timer_stop()\n  augroup END\n  let b:has_timer = 1\n  call s:timer_start()\nendfunction\n\nfunction! s:timer_restart()\n  if isdirectory(expand('%:p:h'))\n    call s:timer_stop()\n    call s:timer_start()\n  endif\nendfunction\n\nfunction! s:timer_stop()\n  if s:timer_id\n    call timer_stop(s:timer_id)\n    let s:timer_id = 0\n  endif\nendfunction\n\nfunction! s:timer_start()\n  let s:timer_id = timer_start(go#config#Updatetime(), function('s:handler'))\nendfunction\n\nfunction! s:handler(timer_id)\n  if go#config#AutoTypeInfo()\n    call go#tool#Info(0)\n  endif\n  if go#config#AutoSameids()\n    call go#sameids#SameIds(0)\n  endif\n  let s:timer_id = 0\nendfunction\n\nfunction! go#auto#fmt_autosave()\n  if !(isdirectory(expand('%:p:h')) && resolve(expand('<afile>:p')) == expand('%:p'))\n    return\n  endif\n\n  if !(go#config#FmtAutosave() || go#config#ImportsAutosave())\n    return\n  endif\n\n  \" Order matters when formatting and adjusting imports, because of gopls'\n  \" support for gofumpt. Gofumpt formatting will group all imports that look\n  \" like a stdlib package (e.g. there's no '.' in the package path) together.\n  \" When the local setting is provided, the only way to get the local imports\n  \" grouped separately when gofumpt is used to format is to format first and\n  \" then organize imports.\n\n  if go#config#FmtAutosave() && !(go#config#ImportsAutosave() && go#config#ImportsMode() == 'goimports')\n    call go#fmt#Format(0)\n\n    \" return early when the imports mode is goimports, because there's no need\n    \" to format again when goimports was run\n    if go#config#FmtCommand() == 'goimports'\n      return\n    endif\n  endif\n\n  if !go#config#ImportsAutosave()\n    return\n  endif\n\n  call go#fmt#Format(1)\nendfunction\n\nfunction! go#auto#metalinter_autosave()\n  if !go#config#MetalinterAutosave() || !isdirectory(expand('%:p:h'))\n    return\n  endif\n\n  \" run gometalinter on save\n  call go#lint#Gometa(!g:go_jump_to_error, 1)\nendfunction\n\nfunction! go#auto#modfmt_autosave()\n  if !(go#config#ModFmtAutosave() && isdirectory(expand('%:p:h')) && resolve(expand('<afile>:p')) == expand('%:p'))\n    return\n  endif\n\n  \" go.mod code formatting on save\n  call go#mod#Format()\nendfunction\n\nfunction! go#auto#asmfmt_autosave()\n  if !(go#config#AsmfmtAutosave() && isdirectory(expand('%:p:h')) && resolve(expand('<afile>:p')) == expand('%:p'))\n    return\n  endif\n\n  \" Go asm formatting on save\n  call go#asmfmt#Format()\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/calls.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! go#calls#Callers() abort\n  if !go#config#GoplsEnabled()\n    call go#util#EchoError(\"gopls is disabled\")\n    return\n  endif\n  let [l:line, l:col] = getpos('.')[1:2]\n  let [l:line, l:col] = go#lsp#lsp#Position(l:line, l:col)\n  let l:fname = expand('%:p')\n  call go#lsp#Callers(l:fname, l:line, l:col, funcref('s:parse_output', ['callers']))\n  return\nendfunction\n\n\" This uses Vim's errorformat to parse the output and put it into a quickfix\n\" or locationlist.\nfunction! s:parse_output(mode, output) abort\n  let errformat = \",%f:%l:%c:\\ %m\"\n  let l:listtype = go#list#Type(\"GoCallers\")\n  call go#list#ParseFormat(l:listtype, errformat, a:output, a:mode, 0)\n\n  let errors = go#list#Get(l:listtype)\n  call go#list#Window(l:listtype, len(errors))\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/calls_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nscriptencoding utf-8\n\nfunc! Test_Callers() abort\n  let l:wd = getcwd()\n  try\n    let l:tmp = gotest#write_file('calls/caller.go', [\n          \\ 'package main',\n          \\ '',\n          \\ 'import \"fmt\"',\n          \\ '',\n          \\ 'func Quux() {}',\n          \\ '',\n          \\ 'func main() {',\n          \\ \"\\tQ\\x1fuux()\",\n          \\ \"\\tQuux()\",\n          \\ '',\n          \\ \"\\tfmt.Println(\\\"vim-go\\\")\",\n          \\ '}',\n        \\ ])\n\n    let l:expected = [\n          \\ {'lnum': 8, 'bufnr': bufnr(''), 'col': 2, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'main'},\n          \\ {'lnum': 9, 'bufnr': bufnr(''), 'col': 2, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'main'},\n        \\ ]\n\n    call go#calls#Callers()\n\n    let l:actual = getloclist(0)\n    let l:start = reltime()\n    while len(l:actual) != len(l:expected) && reltimefloat(reltime(l:start)) < 10\n      sleep 100m\n      let l:actual = getloclist(0)\n    endwhile\n\n    call gotest#assert_quickfix(l:actual, l:expected)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/cmd.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! go#cmd#autowrite() abort\n  if &autowrite == 1 || &autowriteall == 1\n    silent! wall\n  else\n    for l:nr in range(0, bufnr('$'))\n      if buflisted(l:nr) && getbufvar(l:nr, '&modified')\n        \" Sleep one second to make sure people see the message. Otherwise it is\n        \" often immediately overwritten by the async messages (which also\n        \" doesn't invoke the \"hit ENTER\" prompt).\n        call go#util#EchoWarning('[No write since last change]')\n        sleep 1\n        return\n      endif\n    endfor\n  endif\nendfunction\n\n\" Build builds the source code without producing any output binary. We live in\n\" an editor so the best is to build it to catch errors and fix them. By\n\" default it tries to call simply 'go build', but it first tries to get all\n\" dependent files for the current folder and passes it to go build.\nfunction! go#cmd#Build(bang, ...) abort\n  \" Create our command arguments. go build discards any results when it\n  \" compiles multiple packages. So we pass the `errors` package just as an\n  \" placeholder with the current folder (indicated with '.').\n  let l:args =\n        \\ ['build', '-tags', go#config#BuildTags()] +\n        \\ map(copy(a:000), \"expand(v:val)\") +\n        \\ [\".\", \"errors\"]\n\n  \" Vim and Neovim async\n  if go#util#has_job()\n    call s:cmd_job({\n          \\ 'cmd': ['go'] + args,\n          \\ 'bang': a:bang,\n          \\ 'for': 'GoBuild',\n          \\ 'statustype': 'build'\n          \\})\n\n  \" Vim without async\n  else\n    let l:status = {\n          \\ 'desc': 'current status',\n          \\ 'type': 'build',\n          \\ 'state': \"started\",\n          \\ }\n    call go#statusline#Update(expand('%:p:h'), l:status)\n\n    let default_makeprg = &makeprg\n    let &makeprg = \"go \" . join(go#util#Shelllist(args), ' ')\n\n    let l:listtype = go#list#Type(\"GoBuild\")\n    \" execute make inside the source folder so we can parse the errors\n    \" correctly\n    try\n      let l:dir = go#util#Chdir(expand(\"%:p:h\"))\n      if l:listtype == \"locationlist\"\n        silent! exe 'lmake!'\n      else\n        silent! exe 'make!'\n      endif\n      redraw!\n    finally\n      call go#util#Chdir(l:dir)\n      let &makeprg = default_makeprg\n    endtry\n\n    let errors = go#list#Get(l:listtype)\n    call go#list#Window(l:listtype, len(errors))\n    if !empty(errors) && !a:bang\n      call go#list#JumpToFirst(l:listtype)\n      let l:status.state = 'failed'\n    else\n      let l:status.state = 'success'\n      if go#config#EchoCommandInfo()\n        call go#util#EchoSuccess(\"[build] SUCCESS\")\n      endif\n    endif\n    call go#statusline#Update(expand('%:p:h'), l:status)\n  endif\n\nendfunction\n\n\n\" BuildTags sets or shows the current build tags used for tools\nfunction! go#cmd#BuildTags(bang, ...) abort\n  if a:0\n    let v = a:1\n    if v == '\"\"' || v == \"''\"\n      let v = \"\"\n    endif\n    call go#config#SetBuildTags(v)\n    let tags = go#config#BuildTags()\n    if empty(tags)\n      call go#util#EchoSuccess(\"build tags are cleared\")\n    else\n      call go#util#EchoSuccess(\"build tags are changed to: \" . tags)\n    endif\n\n    return\n  endif\n\n  let tags = go#config#BuildTags()\n  if empty(tags)\n    call go#util#EchoSuccess(\"build tags are not set\")\n  else\n    call go#util#EchoSuccess(\"current build tags: \" . tags)\n  endif\nendfunction\n\n\n\" Run runs the current file (and their dependencies if any) in a new terminal.\nfunction! go#cmd#RunTerm(bang, mode, files) abort\n  let cmd = [\"go\", \"run\"]\n  if len(go#config#BuildTags()) > 0\n    call extend(cmd, [\"-tags\", go#config#BuildTags()])\n  endif\n\n  if empty(a:files)\n    call extend(cmd, go#tool#Files())\n  else\n    call extend(cmd, map(copy(a:files), funcref('s:expandRunArgs')))\n  endif\n  call go#term#newmode(a:bang, cmd, s:runerrorformat(), a:mode)\nendfunction\n\n\" Run runs the current file (and their dependencies if any) and outputs it.\n\" This is intended to test small programs and play with them. It's not\n\" suitable for long running apps, because vim is blocking by default and\n\" calling long running apps will block the whole UI.\nfunction! go#cmd#Run(bang, ...) abort\n  if go#config#TermEnabled()\n    call go#cmd#RunTerm(a:bang, '', a:000)\n    return\n  endif\n\n  if go#util#has_job()\n    \" NOTE(arslan): 'term': 'open' case is not implement for +jobs. This means\n    \" executions waiting for stdin will not work. That's why we don't do\n    \" anything. Once this is implemented we're going to make :GoRun async\n  endif\n\n  let l:status = {\n        \\ 'desc': 'current status',\n        \\ 'type': 'run',\n        \\ 'state': \"started\",\n        \\ }\n\n  call go#statusline#Update(expand('%:p:h'), l:status)\n\n  let l:cmd = ['go', 'run']\n  let l:tags = go#config#BuildTags()\n  if len(l:tags) > 0\n    let l:cmd = l:cmd + ['-tags', l:tags]\n  endif\n\n  if a:0 == 0\n    let l:files = go#tool#Files()\n  else\n    let l:files = map(copy(a:000), funcref('s:expandRunArgs'))\n  endif\n\n  let l:cmd = l:cmd + l:files\n\n  if go#util#IsWin()\n    if go#util#HasDebug('shell-commands')\n      call go#util#EchoInfo(printf('shell command: %s', string(l:cmd)))\n    endif\n    try\n      let l:dir = go#util#Chdir(expand(\"%:p:h\"))\n      exec printf('!%s', go#util#Shelljoin(l:cmd, 1))\n    finally\n      call go#util#Chdir(l:dir)\n    endtry\n\n    let l:status.state = 'success'\n    if v:shell_error\n      let l:status.state = 'failed'\n      if go#config#EchoCommandInfo()\n        redraws!\n        call go#util#EchoError('[run] FAILED')\n      endif\n    else\n      if go#config#EchoCommandInfo()\n        redraws!\n        call go#util#EchoSuccess('[run] SUCCESS')\n      endif\n    endif\n\n    call go#statusline#Update(expand('%:p:h'), l:status)\n    return\n  endif\n\n  \" :make expands '%' and '#' wildcards, so they must also be escaped\n  let l:default_makeprg = &makeprg\n  let &makeprg = go#util#Shelljoin(l:cmd, 1)\n\n  let l:listtype = go#list#Type(\"GoRun\")\n\n  let l:status.state = 'success'\n\n  let l:dir = go#util#Chdir(expand(\"%:p:h\"))\n  try\n    \" backup user's errorformat, will be restored once we are finished\n    let l:old_errorformat = &errorformat\n    let &errorformat = s:runerrorformat()\n\n    if go#util#HasDebug('shell-commands')\n      call go#util#EchoInfo(printf('shell command: %s', string(l:cmd)))\n    endif\n\n    if l:listtype == \"locationlist\"\n      exe 'lmake!'\n    else\n      exe 'make!'\n    endif\n  finally\n    call go#util#Chdir(l:dir)\n    let &errorformat = l:old_errorformat\n    let &makeprg = l:default_makeprg\n  endtry\n\n  let l:errors = go#list#Get(l:listtype)\n\n  call go#list#Window(l:listtype, len(l:errors))\n  if !empty(l:errors)\n    let l:status.state = 'failed'\n    if !a:bang\n      call go#list#JumpToFirst(l:listtype)\n    endif\n  endif\n  call go#statusline#Update(expand('%:p:h'), l:status)\nendfunction\n\n\" Install installs the package by simple calling 'go install'. If any argument\n\" is given(which are passed directly to 'go install') it tries to install\n\" those packages. Errors are populated in the location window.\nfunction! go#cmd#Install(bang, ...) abort\n  \" use vim's job functionality to call it asynchronously\n  if go#util#has_job()\n    \" expand all wildcards(i.e: '%' to the current file name)\n    let goargs = map(copy(a:000), \"expand(v:val)\")\n\n    call s:cmd_job({\n          \\ 'cmd': ['go', 'install', '-tags', go#config#BuildTags()] + goargs,\n          \\ 'bang': a:bang,\n          \\ 'for': 'GoInstall',\n          \\ 'statustype': 'install'\n          \\})\n    return\n  endif\n\n  let default_makeprg = &makeprg\n\n  \" :make expands '%' and '#' wildcards, so they must also be escaped\n  let goargs = go#util#Shelljoin(map(copy(a:000), \"expand(v:val)\"), 1)\n  let &makeprg = \"go install \" . goargs\n\n  let l:listtype = go#list#Type(\"GoInstall\")\n  \" execute make inside the source folder so we can parse the errors\n  \" correctly\n  try\n    let l:dir = go#util#Chdir(expand(\"%:p:h\"))\n    if l:listtype == \"locationlist\"\n      silent! exe 'lmake!'\n    else\n      silent! exe 'make!'\n    endif\n    redraw!\n  finally\n    call go#util#Chdir(l:dir)\n    let &makeprg = default_makeprg\n  endtry\n\n  let errors = go#list#Get(l:listtype)\n  call go#list#Window(l:listtype, len(errors))\n  if !empty(errors) && !a:bang\n    call go#list#JumpToFirst(l:listtype)\n  else\n    call go#util#EchoSuccess(\"installed to \". go#path#Default())\n  endif\nendfunction\n\n\" Generate runs 'go generate' in similar fashion to go#cmd#Build()\nfunction! go#cmd#Generate(bang, ...) abort\n  let default_makeprg = &makeprg\n\n  \" :make expands '%' and '#' wildcards, so they must also be escaped\n  let goargs = go#util#Shelljoin(map(copy(a:000), \"expand(v:val)\"), 1)\n  if go#util#ShellError() != 0\n    let &makeprg = \"go generate \" . goargs\n  else\n    let gofiles = go#util#Shelljoin(go#tool#Files(), 1)\n    let &makeprg = \"go generate \" . goargs . ' ' . gofiles\n  endif\n\n  let l:status = {\n        \\ 'desc': 'current status',\n        \\ 'type': 'generate',\n        \\ 'state': \"started\",\n        \\ }\n  call go#statusline#Update(expand('%:p:h'), l:status)\n\n  if go#config#EchoCommandInfo()\n    call go#util#EchoProgress('generating ...')\n  endif\n\n  let l:listtype = go#list#Type(\"GoGenerate\")\n\n  try\n    if l:listtype == \"locationlist\"\n      silent! exe 'lmake!'\n    else\n      silent! exe 'make!'\n    endif\n  finally\n    redraw!\n    let &makeprg = default_makeprg\n  endtry\n\n  let errors = go#list#Get(l:listtype)\n  call go#list#Window(l:listtype, len(errors))\n  if !empty(errors)\n    let l:status.state = 'failed'\n    if !a:bang\n      call go#list#JumpToFirst(l:listtype)\n    endif\n  else\n    let l:status.state = 'success'\n    if go#config#EchoCommandInfo()\n      redraws!\n      call go#util#EchoSuccess('[generate] SUCCESS')\n    endif\n  endif\n  call go#statusline#Update(expand('%:p:h'), l:status)\nendfunction\n\nfunction! s:runerrorformat()\n  let l:panicaddress = \"%\\\\t%#%f:%l +0x%[0-9A-Fa-f]%\\\\+\"\n  let l:errorformat = '%A' . l:panicaddress . \",\" . &errorformat\n  return l:errorformat\nendfunction\n\n\" s:expandRunArgs expands arguments for go#cmd#Run according to the\n\" documentation of :GoRun. When val is a readable file, it is expanded to the\n\" full path so that go run can be executed in the current buffer's directory.\n\" val is return unaltered otherwise to support non-file arguments to go run.\nfunction! s:expandRunArgs(idx, val) abort\n  let l:val = expand(a:val)\n  if !filereadable(l:val)\n    return l:val\n  endif\n\n  return fnamemodify(l:val, ':p')\nendfunction\n\" ---------------------\n\" | Vim job callbacks |\n\" ---------------------\n\nfunction! s:cmd_job(args) abort\n  \" autowrite is not enabled for jobs\n  call go#cmd#autowrite()\n\n  call go#job#Spawn(a:args.cmd, a:args)\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/cmd_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunc! Test_GoBuildErrors()\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let l:filename = 'cmd/bad.go'\n    let l:tmp = gotest#load_fixture(l:filename)\n\n    \" set the compiler type so that the errorformat option will be set\n    \" correctly.\n    compiler go\n\n    let expected = [{'lnum': 4, 'bufnr': bufnr('%'), 'col': 2, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'undefined: notafunc'}]\n    \" clear the quickfix lists\n    call setqflist([], 'r')\n\n    call go#cmd#Build(1)\n\n    let actual = getqflist()\n    let start = reltime()\n    while len(actual) == 0 && reltimefloat(reltime(start)) < 10\n      sleep 100m\n      let actual = getqflist()\n    endwhile\n\n    call gotest#assert_quickfix(actual, l:expected)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/complete.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\n\" go#complete#GoInfo returns the description of the identifier under the\n\" cursor.\nfunction! go#complete#GetInfo() abort\n  return go#lsp#GetInfo()\nendfunction\n\nfunction! go#complete#Complete(findstart, base) abort\n  if !go#config#GoplsEnabled()\n    return -3\n  endif\n\n  let l:state = {'done': 0, 'matches': [], 'start': -1}\n\n  function! s:handler(state, start, matches) abort dict\n    let a:state.start = a:start\n    let a:state.matches = a:matches\n    let a:state.done = 1\n  endfunction\n\n  \"findstart = 1 when we need to get the start of the match\n  if a:findstart == 1\n    let [l:line, l:col] = getpos('.')[1:2]\n    let [l:line, l:col] = go#lsp#lsp#Position(l:line, l:col-1)\n    let l:completion = go#lsp#Completion(expand('%:p'), l:line, l:col, funcref('s:handler', [l:state]))\n    if l:completion\n      return -3\n    endif\n\n    while !l:state.done\n      sleep 10m\n    endwhile\n\n    if len(l:state.matches) == 0\n      \" no matches. cancel and leave completion mode.\n      call go#util#EchoInfo(\"no matches\")\n      return -3\n    endif\n\n    let s:completions = l:state.matches\n\n    return go#lsp#lsp#PositionOf(getline(l:line+1), l:state.start-1)\n  else \"findstart = 0 when we need to return the list of completions\n    return s:completions\n  endif\nendfunction\n\nfunction! go#complete#ToggleAutoTypeInfo() abort\n  if go#config#AutoTypeInfo()\n    call go#config#SetAutoTypeInfo(0)\n    call go#util#EchoProgress(\"auto type info disabled\")\n  else\n    call go#config#SetAutoTypeInfo(1)\n    call go#util#EchoProgress(\"auto type info enabled\")\n  endif\n  call go#auto#update_autocmd()\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/complete_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunc! Test_GetInfo_gopls()\n    let g:go_info_mode = 'gopls'\n    call s:getinfo()\nendfunction\n\nfunc! s:getinfo()\n    let l:filename = 'complete/complete.go'\n    let l:wd = getcwd()\n    let l:tmp = gotest#load_fixture(l:filename)\n    try\n      call cursor(8, 3)\n\n      let expected = 'func Example(s string)'\n      let actual = go#complete#GetInfo()\n      call assert_equal(expected, actual)\n    finally\n      call go#util#Chdir(l:wd)\n      call delete(l:tmp, 'rf')\n    endtry\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/config.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! go#config#ListTypeCommands() abort\n  return get(g:, 'go_list_type_commands', {})\nendfunction\n\nfunction! go#config#VersionWarning() abort\n  return get(g:, 'go_version_warning', 1)\nendfunction\n\nfunction! go#config#BuildTags() abort\n  return get(g:, 'go_build_tags', '')\nendfunction\n\nfunction! go#config#SetBuildTags(value) abort\n  if a:value is ''\n    silent! unlet g:go_build_tags\n    call go#lsp#ResetWorkspaceDirectories()\n    return\n  endif\n\n  let g:go_build_tags = a:value\n  call go#lsp#ResetWorkspaceDirectories()\nendfunction\n\nfunction! go#config#TestTimeout() abort\n return get(g:, 'go_test_timeout', '10s')\nendfunction\n\nfunction! go#config#TestShowName() abort\n  return get(g:, 'go_test_show_name', 0)\nendfunction\n\nfunction! go#config#TermHeight() abort\n  return get(g:, 'go_term_height', winheight(0))\nendfunction\n\nfunction! go#config#TermWidth() abort\n  return get(g:, 'go_term_width', winwidth(0))\nendfunction\n\nfunction! go#config#TermMode() abort\n  return get(g:, 'go_term_mode', 'vsplit')\nendfunction\n\nfunction! go#config#TermCloseOnExit() abort\n  return get(g:, 'go_term_close_on_exit', 1)\nendfunction\n\nfunction! go#config#TermReuse() abort\n  return get(g:, 'go_term_reuse', 0)\nendfunction\n\nfunction! go#config#SetTermCloseOnExit(value) abort\n  let g:go_term_close_on_exit = a:value\nendfunction\n\nfunction! go#config#TermEnabled() abort\n  \" nvim always support\n  \" vim will support if terminal feature exists\n  let l:support = has('nvim') || has('terminal')\n  return support && get(g:, 'go_term_enabled', 0)\nendfunction\n\nfunction! go#config#SetTermEnabled(value) abort\n  let g:go_term_enabled = a:value\nendfunction\n\nfunction! go#config#TemplateUsePkg() abort\n  return get(g:, 'go_template_use_pkg', 0)\nendfunction\n\nfunction! go#config#TemplateTestFile() abort\n  return get(g:, 'go_template_test_file', \"hello_world_test.go\")\nendfunction\n\nfunction! go#config#TemplateFile() abort\n  return get(g:, 'go_template_file', \"hello_world.go\")\nendfunction\n\nfunction! go#config#StatuslineDuration() abort\n  return get(g:, 'go_statusline_duration', 60000)\nendfunction\n\nfunction! go#config#SnippetEngine() abort\n  let l:engine = get(g:, 'go_snippet_engine', 'automatic')\n  if l:engine is? \"automatic\"\n    if get(g:, 'did_plugin_ultisnips') is 1\n      let l:engine = 'ultisnips'\n    elseif get(g:, 'loaded_neosnippet') is 1\n      let l:engine = 'neosnippet'\n    elseif get(g:, 'loaded_minisnip') is 1\n      let l:engine = 'minisnip'\n    endif\n  endif\n\n  return l:engine\nendfunction\n\nfunction! go#config#PlayBrowserCommand() abort\n    if go#util#IsWin()\n        let go_play_browser_command = '!start rundll32 url.dll,FileProtocolHandler %URL%'\n    elseif go#util#IsMac()\n        let go_play_browser_command = 'open %URL%'\n    elseif executable('xdg-open')\n        let go_play_browser_command = 'xdg-open %URL%'\n    elseif executable('firefox')\n        let go_play_browser_command = 'firefox %URL% &'\n    elseif executable('chromium')\n        let go_play_browser_command = 'chromium %URL% &'\n    else\n        let go_play_browser_command = ''\n    endif\n\n    return get(g:, 'go_play_browser_command', go_play_browser_command)\nendfunction\n\nfunction! go#config#MetalinterDeadline() abort\n  \" gometalinter has a default deadline of 5 seconds only when asynchronous\n  \" jobs are not supported.\n\n  let deadline = '5s'\n  if go#util#has_job() && has('lambda')\n    let deadline = ''\n  endif\n\n  return get(g:, 'go_metalinter_deadline', deadline)\nendfunction\n\nfunction! go#config#ListType() abort\n  return get(g:, 'go_list_type', '')\nendfunction\n\nfunction! go#config#ListAutoclose() abort\n  return get(g:, 'go_list_autoclose', 1)\nendfunction\n\nfunction! go#config#EchoCommandInfo() abort\n  return get(g:, 'go_echo_command_info', 1)\nendfunction\n\nfunction! go#config#DocUrl() abort\n  let godoc_url = get(g:, 'go_doc_url', 'https://pkg.go.dev')\n  if godoc_url isnot 'https://pkg.go.dev'\n    \" strip last '/' character if available\n    let last_char = strlen(godoc_url) - 1\n    if godoc_url[last_char] == '/'\n      let godoc_url = strpart(godoc_url, 0, last_char)\n    endif\n    \" custom godoc installations expect /pkg before package names\n    let godoc_url .= \"/pkg\"\n  endif\n  return godoc_url\nendfunction\n\nfunction! go#config#DocPopupWindow() abort\n  return get(g:, 'go_doc_popup_window', 0)\nendfunction\nfunction! go#config#DefReuseBuffer() abort\n  return get(g:, 'go_def_reuse_buffer', 0)\nendfunction\n\nfunction! go#config#DefMode() abort\n  return get(g:, 'go_def_mode', 'gopls')\nendfunction\n\nfunction! go#config#DeclsIncludes() abort\n  return get(g:, 'go_decls_includes', 'func,type')\nendfunction\n\nfunction! go#config#Debug() abort\n  return get(g:, 'go_debug', [])\nendfunction\n\nfunction! go#config#DebugLogDelay() abort\n  return get(g:, 'go_debug_log_delay', 10)\nendfunction\n\nfunction! go#config#DebugWindows() abort\n  return get(g:, 'go_debug_windows', {\n            \\ 'vars':  'leftabove 30vnew',\n            \\ 'stack': 'leftabove 20new',\n            \\ 'goroutines': 'botright 10new',\n            \\ 'out':        'botright 5new',\n            \\ }\n         \\ )\n\nendfunction\n\nfunction! go#config#DebugSubstitutePaths() abort\n  return get(g:, 'go_debug_substitute_paths', [])\nendfunction\n\nfunction! go#config#DebugPreserveLayout() abort\n  return get(g:, 'go_debug_preserve_layout', 0)\nendfunction\n\nfunction! go#config#DebugAddress() abort\n  return get(g:, 'go_debug_address', '127.0.0.1:8181')\nendfunction\n\nfunction! go#config#DebugCommands() abort\n  \" make sure g:go_debug_commands is set so that it can be added to easily.\n  let g:go_debug_commands = get(g:, 'go_debug_commands', [])\n  return g:go_debug_commands\nendfunction\n\nfunction! go#config#DebugLogOutput() abort\n  return get(g:, 'go_debug_log_output', 'debugger,rpc')\nendfunction\n\nfunction! go#config#LspLog() abort\n  \" make sure g:go_lsp_log is set so that it can be added to easily.\n  let g:go_lsp_log = get(g:, 'go_lsp_log', [])\n  return g:go_lsp_log\nendfunction\n\nfunction! go#config#SetDebugDiag(value) abort\n  let g:go_debug_diag = a:value\nendfunction\n\nfunction! go#config#AutoSameids() abort\n    return get(g:, 'go_auto_sameids', 0)\nendfunction\n\nfunction! go#config#SetAutoSameids(value) abort\n  let g:go_auto_sameids = a:value\nendfunction\n\nfunction! go#config#AddtagsTransform() abort\n  return get(g:, 'go_addtags_transform', \"snakecase\")\nendfunction\n\nfunction! go#config#AddtagsSkipUnexported() abort\n  return get(g:, 'go_addtags_skip_unexported', 0)\nendfunction\n\nfunction! go#config#TemplateAutocreate() abort\n  return get(g:, \"go_template_autocreate\", 1)\nendfunction\n\nfunction! go#config#SetTemplateAutocreate(value) abort\n  let g:go_template_autocreate = a:value\nendfunction\n\nlet s:default_metalinter = 'staticcheck'\nfunction! go#config#MetalinterCommand() abort\n  return get(g:, 'go_metalinter_command', s:default_metalinter)\nendfunction\n\nfunction! go#config#MetalinterAutosaveEnabled() abort\n  let l:default = []\n  if get(g:, 'go_metalinter_command', s:default_metalinter) == 'golangci-lint'\n    let l:default = ['govet', 'revive']\n  endif\n\n  return get(g:, 'go_metalinter_autosave_enabled', l:default)\nendfunction\n\nfunction! go#config#MetalinterEnabled() abort\n  let l:default = []\n  if get(g:, 'go_metalinter_command', s:default_metalinter) == 'golangci-lint'\n    let l:default = ['govet', 'revive', 'errcheck']\n  endif\n\n  return get(g:, 'go_metalinter_enabled', l:default)\nendfunction\n\nfunction! go#config#GolintBin() abort\n  return get(g:, \"go_golint_bin\", \"revive\")\nendfunction\n\nfunction! go#config#ErrcheckBin() abort\n  return get(g:, \"go_errcheck_bin\", \"errcheck\")\nendfunction\n\nfunction! go#config#MetalinterAutosave() abort\n  return get(g:, \"go_metalinter_autosave\", 0)\nendfunction\n\nfunction! go#config#SetMetalinterAutosave(value) abort\n  let g:go_metalinter_autosave = a:value\nendfunction\n\nfunction! go#config#ListHeight() abort\n  return get(g:, \"go_list_height\", 0)\nendfunction\n\nfunction! go#config#FmtAutosave() abort\n\treturn get(g:, \"go_fmt_autosave\", 1)\nendfunction\n\nfunction! go#config#ImportsAutosave() abort\n  return get(g:, 'go_imports_autosave', 1)\nendfunction\n\nfunction! go#config#SetFmtAutosave(value) abort\n  let g:go_fmt_autosave = a:value\nendfunction\n\nfunction! go#config#AsmfmtAutosave() abort\n  return get(g:, \"go_asmfmt_autosave\", 0)\nendfunction\n\nfunction! go#config#SetAsmfmtAutosave(value) abort\n  let g:go_asmfmt_autosave = a:value\nendfunction\n\nfunction! go#config#ModFmtAutosave() abort\n\treturn get(g:, \"go_mod_fmt_autosave\", 1)\nendfunction\n\nfunction! go#config#SetModFmtAutosave(value) abort\n  let g:go_mod_fmt_autosave = a:value\nendfunction\n\nfunction! go#config#DocMaxHeight() abort\n  return get(g:, \"go_doc_max_height\", 20)\nendfunction\n\nfunction! go#config#AutoTypeInfo() abort\n  return get(g:, \"go_auto_type_info\", 0)\nendfunction\n\nfunction! go#config#SetAutoTypeInfo(value) abort\n  let g:go_auto_type_info = a:value\nendfunction\n\nfunction! go#config#AlternateMode() abort\n  return get(g:, \"go_alternate_mode\", \"edit\")\nendfunction\n\nfunction! go#config#DeclsMode() abort\n  return get(g:, \"go_decls_mode\", \"\")\nendfunction\n\nfunction! go#config#FmtCommand() abort\n  return get(g:, \"go_fmt_command\", go#config#GoplsEnabled() ? 'gopls' : 'gofmt')\nendfunction\n\nfunction! go#config#ImportsMode() abort\n  return get(g:, \"go_imports_mode\", go#config#GoplsEnabled() ? 'gopls' : 'goimports')\nendfunction\n\nfunction! go#config#FmtOptions() abort\n  return get(b:, \"go_fmt_options\", get(g:, \"go_fmt_options\", {}))\nendfunction\n\nfunction! go#config#FmtFailSilently() abort\n  return get(g:, \"go_fmt_fail_silently\", 0)\nendfunction\n\nfunction! go#config#FmtExperimental() abort\n  return get(g:, \"go_fmt_experimental\", 0 )\nendfunction\n\nfunction! go#config#PlayOpenBrowser() abort\n  return get(g:, \"go_play_open_browser\", 1)\nendfunction\n\nfunction! go#config#RenameCommand() abort\n  \" delegate to go#config#GorenameBin for backwards compatability.\n  return get(g:, \"go_rename_command\", go#config#GorenameBin())\nendfunction\n\nfunction! go#config#GorenameBin() abort\n  return get(g:, \"go_gorename_bin\", 'gopls')\nendfunction\n\nfunction! go#config#GorenamePrefill() abort\n  return get(g:, \"go_gorename_prefill\", 'expand(\"<cword>\") =~# \"^[A-Z]\"' .\n          \\ '? go#util#pascalcase(expand(\"<cword>\"))' .\n          \\ ': go#util#camelcase(expand(\"<cword>\"))')\nendfunction\n\nfunction! go#config#TextobjIncludeFunctionDoc() abort\n  return get(g:, \"go_textobj_include_function_doc\", 1)\nendfunction\n\nfunction! go#config#TextobjIncludeVariable() abort\n  return get(g:, \"go_textobj_include_variable\", 1)\nendfunction\n\nfunction! go#config#BinPath() abort\n  return get(g:, \"go_bin_path\", \"\")\nendfunction\n\nfunction! go#config#SearchBinPathFirst() abort\n  return get(g:, 'go_search_bin_path_first', 1)\nendfunction\n\nfunction! go#config#HighlightArrayWhitespaceError() abort\n  return get(g:, 'go_highlight_array_whitespace_error', 0)\nendfunction\n\nfunction! go#config#HighlightChanWhitespaceError() abort\n  return get(g:, 'go_highlight_chan_whitespace_error', 0)\nendfunction\n\nfunction! go#config#HighlightExtraTypes() abort\n  return get(g:, 'go_highlight_extra_types', 0)\nendfunction\n\nfunction! go#config#HighlightSpaceTabError() abort\n  return get(g:, 'go_highlight_space_tab_error', 0)\nendfunction\n\nfunction! go#config#HighlightTrailingWhitespaceError() abort\n  return get(g:, 'go_highlight_trailing_whitespace_error', 0)\nendfunction\n\nfunction! go#config#HighlightOperators() abort\n  return get(g:, 'go_highlight_operators', 0)\nendfunction\n\nfunction! go#config#HighlightFunctions() abort\n  return get(g:, 'go_highlight_functions', 0)\nendfunction\n\nfunction! go#config#HighlightFunctionParameters() abort\n  \" fallback to highlight_function_arguments for backwards compatibility\n  return get(g:, 'go_highlight_function_parameters', get(g:, 'go_highlight_function_arguments', 0))\nendfunction\n\nfunction! go#config#HighlightFunctionCalls() abort\n  return get(g:, 'go_highlight_function_calls', 0)\nendfunction\n\nfunction! go#config#HighlightFields() abort\n  return get(g:, 'go_highlight_fields', 0)\nendfunction\n\nfunction! go#config#HighlightTypes() abort\n  return get(g:, 'go_highlight_types', 0)\nendfunction\n\nfunction! go#config#HighlightBuildConstraints() abort\n  return get(g:, 'go_highlight_build_constraints', 0)\nendfunction\n\nfunction! go#config#HighlightStringSpellcheck() abort\n  return get(g:, 'go_highlight_string_spellcheck', 1)\nendfunction\n\nfunction! go#config#HighlightFormatStrings() abort\n  return get(g:, 'go_highlight_format_strings', 1)\nendfunction\n\nfunction! go#config#HighlightGenerateTags() abort\n  return get(g:, 'go_highlight_generate_tags', 0)\nendfunction\n\nfunction! go#config#HighlightVariableAssignments() abort\n  return get(g:, 'go_highlight_variable_assignments', 0)\nendfunction\n\nfunction! go#config#HighlightVariableDeclarations() abort\n  return get(g:, 'go_highlight_variable_declarations', 0)\nendfunction\n\nfunction! go#config#HighlightDiagnosticErrors() abort\n  return get(g:, 'go_highlight_diagnostic_errors', 1)\nendfunction\n\nfunction! go#config#HighlightDiagnosticWarnings() abort\n  return get(g:, 'go_highlight_diagnostic_warnings', 1)\nendfunction\n\nfunction! go#config#HighlightDebug() abort\n  return get(g:, 'go_highlight_debug', 1)\nendfunction\n\nfunction! go#config#DebugBreakpointSignText() abort\n  return get(g:, 'go_debug_breakpoint_sign_text', '>')\nendfunction\n\nfunction! go#config#FoldEnable(...) abort\n  if a:0 > 0\n    return index(go#config#FoldEnable(), a:1) > -1\n  endif\n  return get(g:, 'go_fold_enable', ['block', 'import', 'varconst', 'package_comment'])\nendfunction\n\nfunction! go#config#EchoGoInfo() abort\n  return get(g:, \"go_echo_go_info\", 1)\nendfunction\n\nfunction! go#config#CodeCompletionEnabled() abort\n  return get(g:, \"go_code_completion_enabled\", 1)\nendfunction\n\nfunction! go#config#CodeCompletionIcase() abort\n  return get(g:, \"go_code_completion_icase\", 0)\nendfunction\n\nfunction! go#config#Updatetime() abort\n  let go_updatetime = get(g:, 'go_updatetime', 800)\n  return go_updatetime == 0 ? &updatetime : go_updatetime\nendfunction\n\nfunction! go#config#ReferrersMode() abort\n  return get(g:, 'go_referrers_mode', 'gopls')\nendfunction\n\nfunction! go#config#ImplementsMode() abort\n  return get(g:, 'go_implements_mode', 'gopls')\nendfunction\n\nfunction! go#config#GoplsCompleteUnimported() abort\n  return get(g:, 'go_gopls_complete_unimported', v:null)\nendfunction\n\nfunction! go#config#GoplsDeepCompletion() abort\n  return get(g:, 'go_gopls_deep_completion', v:null)\nendfunction\n\nfunction! go#config#GoplsMatcher() abort\n  if !exists('g:go_gopls_matcher') && get(g:, 'g:go_gopls_fuzzy_matching', v:null) is 1\n    return 'fuzzy'\n  endif\n  return get(g:, 'go_gopls_matcher', v:null)\nendfunction\n\nfunction! go#config#GoplsStaticCheck() abort\n  return get(g:, 'go_gopls_staticcheck', v:null)\nendfunction\n\nfunction! go#config#GoplsUsePlaceholders() abort\n  return get(g:, 'go_gopls_use_placeholders', v:null)\nendfunction\n\nfunction! go#config#GoplsTempModfile() abort\n  return get(g:, 'go_gopls_temp_modfile', v:null)\nendfunction\n\nfunction! go#config#GoplsAnalyses() abort\n  return get(g:, 'go_gopls_analyses', v:null)\nendfunction\n\nfunction! go#config#GoplsLocal() abort\n  return get(g:, 'go_gopls_local', v:null)\nendfunction\n\nfunction! go#config#GoplsGofumpt() abort\n  return get(g:, 'go_gopls_gofumpt', v:null)\nendfunction\n\nfunction! go#config#GoplsSettings() abort\n  return get(g:, 'go_gopls_settings', v:null)\nendfunction\n\nfunction! go#config#GoplsEnabled() abort\n  return get(g:, 'go_gopls_enabled', 1)\nendfunction\n\n\" TODO(bc): remove support for g:go_diagnostics_enabled;\n\" g:go_diagnostics_level is the replacement.\nfunction! go#config#DiagnosticsEnabled() abort\n  return get(g:, 'go_diagnostics_enabled', 0)\nendfunction\n\nfunction! go#config#DiagnosticsLevel() abort\n  let l:default = 0\n  if has_key(g:, 'go_diagnostics_enabled') && g:go_diagnostics_enabled\n    let l:default = 2\n  endif\n\n  return get(g:, 'go_diagnostics_level', l:default)\nendfunction\n\nfunction! go#config#GoplsOptions() abort\n  return get(g:, 'go_gopls_options', ['-remote=auto'])\nendfunction\n\nfunction! go#config#FillStructMode() abort\n  return get(g:, 'go_fillstruct_mode', 'fillstruct')\nendfunction\n\nfunction! go#config#DebugMappings() abort\n  let l:default = {\n     \\ '(go-debug-continue)':   {'key': '<F5>'},\n     \\ '(go-debug-print)':      {'key': '<F6>'},\n     \\ '(go-debug-breakpoint)': {'key': '<F9>'},\n     \\ '(go-debug-next)':       {'key': '<F10>'},\n     \\ '(go-debug-step)':       {'key': '<F11>'},\n     \\ '(go-debug-halt)':       {'key': '<F8>'},\n  \\ }\n\n  let l:user = deepcopy(get(g:, 'go_debug_mappings', {}))\n\n  return extend(l:user, l:default, 'keep')\nendfunction\n\nfunction! go#config#DocBalloon() abort\n  return get(g:, 'go_doc_balloon', 0)\nendfunction\n\n\" Set the default value. A value of \"1\" is a shortcut for this, for\n\" compatibility reasons.\nif exists(\"g:go_gorename_prefill\") && g:go_gorename_prefill == 1\n  unlet g:go_gorename_prefill\nendif\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/config_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nscriptencoding utf-8\n\nfunc! Test_SetBuildTags() abort\n  if !go#util#has_job()\n    return\n  endif\n\n  try\n    let g:go_def_mode = 'gopls'\n    let l:dir = 'test-fixtures/config/buildtags'\n    let l:jumpstart = [0, 4, 2, 0]\n\n    execute 'e ' . printf('%s/buildtags.go', l:dir)\n    let l:jumpstartbuf = bufnr('')\n\n    call setpos('.', [l:jumpstartbuf, l:jumpstart[1], l:jumpstart[2], 0])\n\n    let l:expectedfilename = printf('%s/foo.go', l:dir)\n\n    let l:expected = [0, 5, 6, 0]\n    call assert_notequal(l:expected, l:jumpstart)\n\n    call go#def#Jump('', 0)\n\n    let l:start = reltime()\n    while getpos('.') != l:expected && reltimefloat(reltime(l:start)) < 10\n      sleep 100m\n    endwhile\n\n    call assert_equal(l:expectedfilename, bufname(\"%\"))\n    call assert_equal(l:expected, getpos('.'))\n\n    execute 'e ' . printf('%s/buildtags.go', l:dir)\n\n    \" prepare to wait for the workspace/configuration request\n    let g:go_debug=['lsp']\n\n    \" set the build constraint\n    call go#config#SetBuildTags('constrained')\n\n    \" wait for the workspace/configuration request\n    let l:lsplog = getbufline('__GOLSP_LOG__', 1, '$')\n    let l:start = reltime()\n    while match(l:lsplog, 'workspace/configuration') == -1 && reltimefloat(reltime(l:start)) < 10\n      sleep 50m\n      let l:lsplog = getbufline('__GOLSP_LOG__', 1, '$')\n    endwhile\n    \" close the __GOLSP_LOG__ window\n    only\n\n    \" verify the cursor position within buildtags.go\n    call setpos('.', [l:jumpstartbuf, l:jumpstart[1], l:jumpstart[2], 0])\n    call assert_equal(l:jumpstart, getpos('.'))\n\n    let l:expectedfilename = printf('%s/constrainedfoo.go', l:dir)\n    let l:expected = [0, 6, 6, 0]\n    call assert_notequal(l:expected, l:jumpstart)\n\n    call go#def#Jump('', 0)\n\n    let l:start = reltime()\n    while getpos('.') != l:expected && reltimefloat(reltime(l:start)) < 10\n      sleep 100m\n    endwhile\n\n    call assert_equal(l:expectedfilename, bufname(\"%\"))\n    call assert_equal(l:expected, getpos('.'))\n\n    let l:lsplog = getbufline('__GOLSP_LOG__', 1, '$')\n\n  finally\n    call go#config#SetBuildTags('')\n  endtry\nendfunc\n\nfunc! Test_GoplsEnabled_Clear() abort\n  if !go#util#has_job()\n    return\n  endif\n\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n\n    let l:tmp = gotest#write_file('gopls_disabled.go', [\n          \\ 'package example',\n          \\ '',\n          \\ 'func Example() {',\n          \\ \"\\tprintln(\" . '\"hello, world!\")',\n          \\ '}',\n          \\ ] )\n\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/coverage.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nlet s:toggle = 0\n\n\" Buffer creates a new cover profile with 'go test -coverprofile' and changes\n\" the current buffers highlighting to show covered and uncovered sections of\n\" the code. If run again it clears the annotation.\nfunction! go#coverage#BufferToggle(bang, ...) abort\n  if s:toggle\n    call go#coverage#Clear()\n    return\n  endif\n\n  if a:0 == 0\n    return call(function('go#coverage#Buffer'), [a:bang])\n  endif\n\n  return call(function('go#coverage#Buffer'), [a:bang] + a:000)\nendfunction\n\n\" Buffer creates a new cover profile with 'go test -coverprofile' and changes\n\" the current buffers highlighting to show covered and uncovered sections of\n\" the code. Calling it again reruns the tests and shows the last updated\n\" coverage.\nfunction! go#coverage#Buffer(bang, ...) abort\n\n  \" check if the version of Vim being tested supports matchaddpos()\n  if !exists(\"*matchaddpos\")\n    call go#util#EchoError(\"GoCoverage is not supported by your version of Vim.\")\n    return -1\n  endif\n\n  \" check if there is any test file, if not we just return\n  try\n    let l:dir = go#util#Chdir(expand(\"%:p:h\"))\n    if empty(glob(\"*_test.go\"))\n      call go#util#EchoError(\"no test files available\")\n      return\n    endif\n  finally\n    call go#util#Chdir(l:dir)\n  endtry\n\n  let s:toggle = 1\n  let l:tmpname = tempname()\n\n  if go#util#has_job()\n    call s:coverage_job({\n          \\ 'cmd': ['go', 'test', '-tags', go#config#BuildTags(), '-coverprofile', l:tmpname] + a:000,\n          \\ 'complete': function('s:coverage_callback', [l:tmpname]),\n          \\ 'bang': a:bang,\n          \\ 'for': 'GoTest',\n          \\ 'statustype': 'coverage',\n          \\ })\n    return\n  endif\n\n  if go#config#EchoCommandInfo()\n    call go#util#EchoProgress(\"testing...\")\n  endif\n\n  let args = [a:bang, 0, \"-coverprofile\", l:tmpname]\n  if a:0\n    call extend(args, a:000)\n  endif\n\n  let id = call('go#test#Test', args)\n\n  if go#util#ShellError() == 0\n    call go#coverage#Overlay(l:tmpname)\n  endif\n\n  call delete(l:tmpname)\nendfunction\n\n\" Clear clears and resets the buffer annotation matches\nfunction! go#coverage#Clear() abort\n  call clearmatches()\n\n  if exists(\"s:toggle\") | let s:toggle = 0 | endif\n\n  \" remove the autocmd we defined\n  augroup vim-go-coverage\n    autocmd! * <buffer>\n  augroup end\nendfunction\n\n\" Browser creates a new cover profile with 'go test -coverprofile' and opens\n\" a new HTML coverage page from that profile in a new browser\nfunction! go#coverage#Browser(bang, ...) abort\n  let l:tmpname = tempname()\n  if go#util#has_job()\n    call s:coverage_job({\n          \\ 'cmd': ['go', 'test', '-tags', go#config#BuildTags(), '-coverprofile', l:tmpname] + a:000,\n          \\ 'complete': function('s:coverage_browser_callback', [l:tmpname]),\n          \\ 'bang': a:bang,\n          \\ 'for': 'GoTest',\n          \\ 'statustype': 'coverage',\n          \\ })\n    return\n  endif\n\n  let args = [a:bang, 0, \"-coverprofile\", l:tmpname]\n  if a:0\n    call extend(args, a:000)\n  endif\n\n  let id = call('go#test#Test', args)\n\n  if go#util#ShellError() == 0\n    call go#util#ExecInDir(['go', 'tool', 'cover', '-html=' . l:tmpname])\n  endif\n\n  call delete(l:tmpname)\nendfunction\n\n\" Parses a single line from the cover file generated via go test -coverprofile\n\" and returns a single coverage profile block.\nfunction! go#coverage#parsegocoverline(line) abort\n  \" file:startline.col,endline.col numstmt count\n  let mx = '\\([^:]\\+\\):\\(\\d\\+\\)\\.\\(\\d\\+\\),\\(\\d\\+\\)\\.\\(\\d\\+\\)\\s\\(\\d\\+\\)\\s\\(\\d\\+\\)'\n  let tokens = matchlist(a:line, mx)\n  let ret = {}\n  let ret.file = tokens[1]\n  let ret.startline  = str2nr(tokens[2])\n  let ret.startcol = str2nr(tokens[3])\n  let ret.endline = str2nr(tokens[4])\n  let ret.endcol = str2nr(tokens[5])\n  let ret.numstmt = tokens[6]\n  let ret.cnt = tokens[7]\n  return ret\nendfunction\n\n\" Generates matches to be added to matchaddpos for the given coverage profile\n\" block\nfunction! go#coverage#genmatch(cov) abort\n  let color = 'goCoverageCovered'\n  if a:cov.cnt == 0\n    let color = 'goCoverageUncover'\n  endif\n\n  let matches = []\n\n  \" if start and end are the same, also specify the byte length\n  \" example: foo.go:92.2,92.65 1 0\n  if a:cov.startline == a:cov.endline\n    call add(matches, {\n          \\ 'group': color,\n          \\ 'pos': [[a:cov.startline, a:cov.startcol, a:cov.endcol - a:cov.startcol]],\n          \\ 'priority': 2,\n          \\ })\n    return matches\n  endif\n\n  \" add start columns. Because we don't know the length of the of\n  \" the line, we assume it is at maximum 200 bytes. I know this is hacky,\n  \" but that's only way of fixing the issue\n  call add(matches, {\n        \\ 'group': color,\n        \\ 'pos': [[a:cov.startline, a:cov.startcol, 200]],\n        \\ 'priority': 2,\n        \\ })\n\n  \" and then the remaining lines\n  let start_line = a:cov.startline\n  while start_line < a:cov.endline\n    let start_line += 1\n    call add(matches, {\n          \\ 'group': color,\n          \\ 'pos': [[start_line]],\n          \\ 'priority': 2,\n          \\ })\n  endwhile\n\n  \" finally end columns\n  call add(matches, {\n        \\ 'group': color,\n        \\ 'pos': [[a:cov.endline, a:cov.endcol-1]],\n        \\ 'priority': 2,\n        \\ })\n\n  return matches\nendfunction\n\n\" Reads the given coverprofile file and annotates the current buffer\nfunction! go#coverage#Overlay(file) abort\n  if !filereadable(a:file)\n    return\n  endif\n  let lines = readfile(a:file)\n\n  \" cover mode, by default it's 'set'. Just here for debugging purposes\n  let mode = lines[0]\n\n  \" contains matches for matchaddpos()\n  let matches = []\n\n  \" first mark all lines as goCoverageNormalText. We use a custom group to not\n  \" interfere with other buffers highlightings. Because the priority is\n  \" lower than the cover and uncover matches, it'll be overridden.\n  let cnt = 1\n  while cnt <= line('$')\n    call add(matches, {'group': 'goCoverageNormalText', 'pos': [cnt], 'priority': 1})\n    let cnt += 1\n  endwhile\n\n  let fname = expand('%')\n\n  \" when called for a test file, run the coverage for the actual file\n  if fname =~# '^\\f\\+_test\\.go$'\n    let l:root = split(fname, '_test.go$')[0]\n    let fname = l:root . \".go\"\n\n    if !filereadable(fname)\n      call go#util#EchoError(\"couldn't find \".fname)\n      return\n    endif\n\n    \" open the alternate file to show the coverage\n    exe \":edit \". fnamemodify(fname, \":p\")\n  endif\n\n  \" cov.file includes only the filename itself, without full path\n  let fname = fnamemodify(fname, \":t\")\n\n  for line in lines[1:]\n    let cov = go#coverage#parsegocoverline(line)\n\n    \" TODO(arslan): for now only include the coverage for the current\n    \" buffer\n    if fname != fnamemodify(cov.file, ':t')\n      continue\n    endif\n\n    call extend(matches, go#coverage#genmatch(cov))\n  endfor\n\n  \" clear the matches if we leave the buffer\n  augroup vim-go-coverage\n    autocmd! * <buffer>\n    autocmd BufWinLeave <buffer> call go#coverage#Clear()\n  augroup end\n\n  for m in matches\n    call matchaddpos(m.group, m.pos)\n  endfor\nendfunction\n\n\n\" ---------------------\n\" | Vim job callbacks |\n\" ---------------------\n\"\nfunction s:coverage_job(args)\n  \" autowrite is not enabled for jobs\n  call go#cmd#autowrite()\n\n  let disabled_term = 0\n  if go#config#TermEnabled()\n    let disabled_term = 1\n    call go#config#SetTermEnabled(0)\n  endif\n\n  call go#job#Spawn(a:args.cmd, a:args)\n\n  if disabled_term\n    call go#config#SetTermEnabled(1)\n  endif\nendfunction\n\n\" coverage_callback is called when the coverage execution is finished\nfunction! s:coverage_callback(coverfile, job, exit_status, data)\n  if a:exit_status == 0\n    call go#coverage#Overlay(a:coverfile)\n  endif\n\n  call delete(a:coverfile)\nendfunction\n\nfunction! s:coverage_browser_callback(coverfile, job, exit_status, data)\n  if a:exit_status == 0\n    call go#util#ExecInDir(['go', 'tool', 'cover', '-html=' . a:coverfile])\n  endif\n\n  call delete(a:coverfile)\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/debug.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nscriptencoding utf-8\n\nif !exists('s:state')\n  let s:state = {\n        \\ 'rpcid': 0,\n        \\ 'running': 0,\n        \\ 'currentThread': {},\n        \\ 'localVars': {},\n        \\ 'functionArgs': {},\n        \\ 'registers': {},\n        \\ 'message': [],\n        \\ 'resultHandlers': {},\n        \\ 'kill_on_detach': v:true,\n      \\ }\n\n  if go#util#HasDebug('debugger-state')\n     call go#config#SetDebugDiag(s:state)\n  endif\nendif\n\nif !exists('s:start_args')\n  let s:start_args = []\nendif\n\nif !exists('s:mapargs')\n  let s:mapargs = {}\nendif\n\nfunction! s:goroutineID() abort\n  return s:state['currentThread'].goroutineID\nendfunction\n\nfunction! s:complete(job, exit_status, data) abort\n  \" copy messages to a:data _only_ when dlv exited non-zero and it was never\n  \" detected as ready (e.g. there was a compiler error).\n  if a:exit_status > 0 && !s:isReady()\n      \" copy messages to data so that vim-go's usual handling of errors from\n      \" async jobs will occur.\n      call extend(a:data, s:state['message'])\n  endif\n\n  \" return early instead of clearing any variables when the current job is not\n  \" a:job\n  if has_key(s:state, 'job') && s:state['job'] != a:job\n    return\n  endif\n\n  if has_key(s:state, 'job')\n    call remove(s:state, 'job')\n  endif\n\n  if has_key(s:state, 'ready')\n    call remove(s:state, 'ready')\n  endif\n\n  if has_key(s:state, 'ch')\n    call remove(s:state, 'ch')\n  endif\n\n  call s:clearState()\nendfunction\n\nlet s:log = []\nlet s:logtimer = 0\nfunction! s:logasync(timer) abort\n  let s:logtimer = 0\n  try\n    let l:name = '__GODEBUG_OUTPUT__'\n    let l:log_winid = bufwinid(l:name)\n    if l:log_winid == -1\n      if !s:isReady() && !has_key(s:state, 'job')\n        return\n      endif\n      let s:logtimer = timer_start(go#config#DebugLogDelay(), function('s:logasync', []))\n      return\n    endif\n\n    try\n      call setbufvar(l:name, '&modifiable', 1)\n      for [l:prefix, l:data] in s:log\n        call remove(s:log, 0)\n        if getbufline(l:name, 1)[0] == ''\n          call setbufline(l:name, '$', printf('%s%s', l:prefix, l:data))\n        else\n          call appendbufline(l:name, '$', printf('%s%s', l:prefix, l:data))\n        endif\n      endfor\n\n      \" Move the window's cursor position without switching to the window\n      call win_execute(l:log_winid, 'normal! G')\n      call setbufvar(l:name, '&modifiable', 0)\n    finally\n    endtry\n  catch\n    call go#util#EchoError(printf('at %s: %s', v:throwpoint, v:exception))\n  finally\n    \" retry when there's an exception.\n    if len(s:log) != 0\n      let s:logtimer = timer_start(go#config#DebugLogDelay(), function('s:logasync', []))\n    endif\n  endtry\nendfunction\n\nfunction! s:logger(prefix, ch, data) abort\n  let l:shouldStart = s:logtimer is 0\n  let s:log = add(s:log, [a:prefix, a:data])\n\n  if l:shouldStart\n    let s:logtimer = timer_start(go#config#DebugLogDelay(), function('s:logasync', []))\n  endif\nendfunction\n\n\" s:call_jsonrpc will call method, passing all of s:call_jsonrpc's optional\n\" arguments in the rpc request's params field.\n\n\" The first argument to s:call_jsonrpc should be a function that takes two\n\" arguments. The first argument will be a function that takes no arguments and will\n\" throw an exception if the response to the request is an error response. The\n\" second argument is the response itself.\nfunction! s:call_jsonrpc(handle_result, method, ...) abort\n  if go#util#HasDebug('debugger-commands')\n    call go#util#EchoInfo('sending to dlv ' . a:method)\n  endif\n\n  let l:args = a:000\n  let s:state['rpcid'] += 1\n  let l:reqid = s:state['rpcid']\n  let l:req_json = json_encode({\n      \\  'id': l:reqid,\n      \\  'method': a:method,\n      \\  'params': l:args,\n      \\})\n\n  try\n    let l:ch = s:state['ch']\n    if has('nvim')\n      call chansend(l:ch, l:req_json)\n    else\n      call ch_sendraw(l:ch, req_json)\n    endif\n\n    let s:state.resultHandlers[l:reqid] = a:handle_result\n\n    if go#util#HasDebug('debugger-commands')\n      let g:go_debug_commands = add(go#config#DebugCommands(), {\n            \\ 'request':  json_decode(l:req_json)\n      \\ })\n    endif\n\n    redraw\n  catch\n    throw substitute(v:exception, '^Vim', '', '')\n  endtry\nendfunction\n\nfunction! s:exited(res) abort\n  if type(a:res) ==# type(v:null)\n    return 0\n  endif\n\n  let state = a:res.result.State\n  return state.exited == v:true\nendfunction\n\n\" Update the location of the current breakpoint or line we're halted on based on\n\" response from dlv.\nfunction! s:update_breakpoint(res) abort\n  if type(a:res) ==# type(v:null)\n    return\n  endif\n\n  let state = a:res.result.State\n  if !has_key(state, 'currentThread')\n    return\n  endif\n\n  let s:state['currentThread'] = state.currentThread\n  let filename = s:substituteRemotePath(state.currentThread.file)\n  if filename == ''\n    return\n  endif\n  let bufs = filter(map(range(1, winnr('$')), '[v:val,bufname(winbufnr(v:val))]'), 'v:val[1]=~\"\\.go$\"')\n  if len(bufs) == 0\n    return\n  endif\n\n  call win_gotoid(win_getid(bufs[0][0]))\n  let linenr = state.currentThread.line\n  let oldfile = fnamemodify(expand('%'), ':p:gs!\\\\!/!')\n  if oldfile != filename\n    silent! exe 'edit' filename\n    \" synchronize breakpoints in case the new filename is not already loaded\n    \" in a buffer.\n    call s:sync_breakpoints()\n  endif\n  silent! exe 'norm!' linenr.'G'\n  silent! normal! zvzz\n  \" TODO(bc): convert to use s:sign_unplace()\n  silent! sign unplace 9999\n  \" TODO(bc): convert to use s:sign_place()\n  silent! exe 'sign place 9999 line=' . linenr . ' name=godebugcurline file=' . filename\n  call s:warn_when_stale(fnamemodify(l:filename, ':p'))\nendfunction\n\n\" Populate the stacktrace window.\nfunction! s:show_stacktrace(check_errors, res) abort\n  try\n    call a:check_errors()\n  catch\n    call go#util#EchoError(printf('could not update stack: %s', v:exception))\n    return\n  endtry\n\n  if type(a:res) isnot type({}) || !has_key(a:res, 'result') || empty(a:res.result)\n    return\n  endif\n\n  let l:stack_win = bufwinnr(bufnr('__GODEBUG_STACKTRACE__'))\n  if l:stack_win == -1\n    return\n  endif\n\n  let l:cur_win = bufwinnr('')\n  exe l:stack_win 'wincmd w'\n\n  try\n    setlocal modifiable\n    silent %delete _\n    for i in range(len(a:res.result.Locations))\n      let loc = a:res.result.Locations[i]\n      if loc.file is# '?' || !has_key(loc, 'function')\n        continue\n      endif\n      call setline(i+1, printf('%s - %s:%d', loc.function.name, s:substituteRemotePath(fnamemodify(loc.file, ':p')), loc.line))\n    endfor\n  finally\n    setlocal nomodifiable\n    exe l:cur_win 'wincmd w'\n  endtry\nendfunction\n\n\" Populate the variable window.\nfunction! s:show_variables() abort\n  let l:var_win = bufwinnr(bufnr('__GODEBUG_VARIABLES__'))\n  if l:var_win == -1\n    return\n  endif\n\n  let l:cur_win = bufwinnr('')\n  exe l:var_win 'wincmd w'\n  try\n    setlocal modifiable\n    silent %delete _\n\n    let v = []\n    let v += ['# Local Variables']\n    if type(get(s:state, 'localVars', [])) is type([])\n      for c in s:state['localVars']\n        let v += split(s:eval_tree(c, 0, 0), \"\\n\")\n      endfor\n    endif\n\n    let v += ['']\n    let v += ['# Function Arguments']\n    if type(get(s:state, 'functionArgs', [])) is type([])\n      for c in s:state['functionArgs']\n        let v += split(s:eval_tree(c, 0, 0), \"\\n\")\n      endfor\n    endif\n\n    let v += ['']\n    let v += ['# Registers']\n    if type(get(s:state, 'registers', [])) is type([])\n      for c in s:state['registers']\n        let v += [printf(\"%s = %s\", c.Name, c.Value)]\n      endfor\n    endif\n\n    call setline(1, v)\n  finally\n    setlocal nomodifiable\n    exe l:cur_win 'wincmd w'\n  endtry\nendfunction\n\nfunction! s:clearState() abort\n  let s:state['running'] = 0\n  let s:state['currentThread'] = {}\n  let s:state['localVars'] = {}\n  let s:state['functionArgs'] = {}\n  let s:state['registers'] = {}\n  let s:state['message'] = []\n\n  silent! sign unplace 9999\nendfunction\n\nfunction! s:stop() abort\n  call s:call_jsonrpc(function('s:noop'), 'RPCServer.Detach', {'kill': s:state['kill_on_detach']})\n\n  if has_key(s:state, 'job')\n    call go#job#Wait(s:state['job'])\n\n    \" while waiting, the s:complete may have already removed job from s:state.\n    if has_key(s:state, 'job')\n      call remove(s:state, 'job')\n    endif\n  endif\n\n  if has_key(s:state, 'ready')\n    call remove(s:state, 'ready')\n  endif\n\n  if has_key(s:state, 'ch')\n    call remove(s:state, 'ch')\n  endif\n  call s:clearState()\nendfunction\n\nfunction! go#debug#Stop() abort\n  \" Remove all commands and add back the default commands.\n  for k in map(split(execute('command GoDebug'), \"\\n\")[1:], 'matchstr(v:val, \"^\\\\s*\\\\zs\\\\S\\\\+\")')\n    try\n      if k is 'Name'\n        continue\n      endif\n      execute(printf('delcommand %s', k))\n    catch\n    endtry\n  endfor\n  command! -nargs=* -complete=customlist,go#package#Complete GoDebugStart call go#debug#Start('debug', <f-args>)\n  command! -nargs=* -complete=customlist,go#package#Complete GoDebugTest  call go#debug#Start('test', <f-args>)\n  command! -nargs=? GoDebugConnect call go#debug#Start('connect', <f-args>)\n  command! -nargs=* GoDebugTestFunc  call go#debug#TestFunc(<f-args>)\n  command! -nargs=1 GoDebugAttach call go#debug#Start('attach', <f-args>)\n  command! -nargs=? GoDebugBreakpoint call go#debug#Breakpoint(<f-args>)\n\n  \" Restore mappings configured prior to debugging.\n  call s:restoreMappings()\n\n  \" remove plug mappings\n  for k in map(split(execute('nmap <Plug>(go-debug-'), \"\\n\"), 'matchstr(v:val, \"^n\\\\s\\\\+\\\\zs\\\\S\\\\+\")')\n    try\n      execute(printf('nunmap %s', k))\n    catch\n    endtry\n  endfor\n\n  call s:stop()\n\n  let bufs = filter(map(range(1, winnr('$')), '[v:val,bufname(winbufnr(v:val))]'), 'v:val[1]=~\"\\.go$\"')\n  if len(bufs) > 0\n    call win_gotoid(win_getid(bufs[0][0]))\n  else\n    wincmd p\n  endif\n\n  let stackbufnr = bufnr('__GODEBUG_STACKTRACE__')\n  if stackbufnr != -1\n    silent! exe bufwinnr(stackbufnr) 'wincmd c'\n  endif\n\n  let varbufnr = bufnr('__GODEBUG_VARIABLES__')\n  if varbufnr != -1\n    silent! exe bufwinnr(varbufnr) 'wincmd c'\n  endif\n\n  let outbufnr = bufnr('__GODEBUG_OUTPUT__')\n  if outbufnr != -1\n    silent! exe bufwinnr(outbufnr) 'wincmd c'\n  endif\n\n  let gorobufnr = bufnr('__GODEBUG_GOROUTINES__')\n  if gorobufnr != -1\n    silent! exe bufwinnr(gorobufnr) 'wincmd c'\n  endif\n\n  if has('balloon_eval')\n    let &ballooneval=s:ballooneval\n    let &balloonexpr=s:balloonexpr\n  endif\n\n  augroup vim-go-debug\n    autocmd!\n  augroup END\n  augroup! vim-go-debug\nendfunction\n\nfunction! s:goto_file() abort\n  let m = matchlist(getline('.'), ' - \\(.*\\):\\([0-9]\\+\\)$')\n  if m[1] == ''\n    return\n  endif\n  let bufs = filter(map(range(1, winnr('$')), '[v:val,bufname(winbufnr(v:val))]'), 'v:val[1]=~\"\\.go$\"')\n  if len(bufs) == 0\n    return\n  endif\n  call win_gotoid(win_getid(bufs[0][0]))\n  let filename = m[1]\n  let linenr = m[2]\n  let oldfile = fnamemodify(expand('%'), ':p:gs!\\\\!/!')\n  if oldfile != filename\n    silent! exe 'edit' filename\n    \" synchronize breakpoints in case the new filename is not already loaded\n    \" in a buffer.\n    call s:sync_breakpoints()\n  endif\n  silent! exe 'norm!' linenr.'G'\n  silent! normal! zvzz\nendfunction\n\nfunction! s:delete_expands()\n  let nr = line('.')\n  while 1\n    let l = getline(nr+1)\n    if empty(l) || l =~ '^\\S'\n      return\n    endif\n    silent! exe (nr+1) . 'd _'\n  endwhile\n  silent! exe 'norm!' nr.'G'\nendfunction\n\nfunction! s:expand_var() abort\n  \" Get name from struct line.\n  let name = matchstr(getline('.'), '^[^:]\\+\\ze: \\*\\?[a-zA-Z0-9-_/\\.]\\+\\({\\.\\.\\.}\\)\\?$')\n  \" Anonymous struct\n  if name == ''\n    let name = matchstr(getline('.'), '^[^:]\\+\\ze: \\*\\?struct {.\\{-}}$')\n  endif\n\n  if name != ''\n    setlocal modifiable\n    let not_open = getline(line('.')+1) !~ '^ '\n    let l = line('.')\n    call s:delete_expands()\n\n    if not_open\n      call append(l, split(s:eval(name), \"\\n\")[1:])\n    endif\n    silent! exe 'norm!' l.'G'\n    setlocal nomodifiable\n    return\n  endif\n\n  \" Expand maps\n  let m = matchlist(getline('.'), '^[^:]\\+\\ze: map.\\{-}\\[\\(\\d\\+\\)\\]$')\n  if len(m) > 0 && m[1] != ''\n    setlocal modifiable\n    let not_open = getline(line('.')+1) !~ '^ '\n    let l = line('.')\n    call s:delete_expands()\n    if not_open\n      \" TODO: Not sure how to do this yet... Need to get keys of the map.\n      \" let vs = ''\n      \" for i in range(0, min([10, m[1]-1]))\n      \"   let vs .= ' ' . s:eval(printf(\"%s[%s]\", m[0], ))\n      \" endfor\n      \" call append(l, split(vs, \"\\n\"))\n    endif\n\n    silent! exe 'norm!' l.'G'\n    setlocal nomodifiable\n    return\n  endif\n\n  \" Expand string.\n  let m = matchlist(getline('.'), '^\\([^:]\\+\\)\\ze: \\(string\\)\\[\\([0-9]\\+\\)\\]\\(: .\\{-}\\)\\?$')\n  if len(m) > 0 && m[1] != ''\n    setlocal modifiable\n    let not_open = getline(line('.')+1) !~ '^ '\n    let l = line('.')\n    call s:delete_expands()\n\n    if not_open\n      let vs = ''\n      for i in range(0, min([10, m[3]-1]))\n        let vs .= ' ' . s:eval(m[1] . '[' . i . ']')\n      endfor\n      call append(l, split(vs, \"\\n\"))\n    endif\n\n    silent! exe 'norm!' l.'G'\n    setlocal nomodifiable\n    return\n  endif\n\n  \" Expand slice.\n  let m = matchlist(getline('.'), '^\\([^:]\\+\\)\\ze: \\(\\[\\]\\w\\{-}\\)\\[\\([0-9]\\+\\)\\]$')\n  if len(m) > 0 && m[1] != ''\n    setlocal modifiable\n    let not_open = getline(line('.')+1) !~ '^ '\n    let l = line('.')\n    call s:delete_expands()\n\n    if not_open\n      let vs = ''\n      for i in range(0, min([10, m[3]-1]))\n        let vs .= ' ' . s:eval(m[1] . '[' . i . ']')\n      endfor\n      call append(l, split(vs, \"\\n\"))\n    endif\n    silent! exe 'norm!' l.'G'\n    setlocal nomodifiable\n    return\n  endif\nendfunction\n\nfunction! s:create_layout() abort\n  let l:winid = win_getid()\n  let l:debugwindows = go#config#DebugWindows()\n  let l:debugpreservelayout = go#config#DebugPreserveLayout()\n\n  if !(empty(l:debugwindows) || l:debugpreservelayout)\n    silent! only!\n  endif\n\n  let winnum = bufwinnr(bufnr('__GODEBUG_STACKTRACE__'))\n  if winnum != -1\n    return\n  endif\n\n  if has_key(l:debugwindows, \"vars\") && l:debugwindows['vars'] != ''\n    exe 'silent ' . l:debugwindows['vars']\n    silent file `='__GODEBUG_VARIABLES__'`\n    setlocal buftype=nofile bufhidden=wipe nomodified nobuflisted noswapfile nowrap nonumber nocursorline\n    setlocal filetype=godebugvariables\n    call append(0, [\"# Local Variables\", \"\", \"# Function Arguments\", \"\", \"# Registers\"])\n    nmap <buffer> <silent> <cr> :<c-u>call <SID>expand_var()<cr>\n    nmap <buffer> q <Plug>(go-debug-stop)\n  endif\n\n  if has_key(l:debugwindows, \"stack\") && l:debugwindows['stack'] != ''\n    exe 'silent ' . l:debugwindows['stack']\n    silent file `='__GODEBUG_STACKTRACE__'`\n    setlocal buftype=nofile bufhidden=wipe nomodified nobuflisted noswapfile nowrap nonumber nocursorline\n    setlocal filetype=godebugstacktrace\n    nmap <buffer> <cr> :<c-u>call <SID>goto_file()<cr>\n    nmap <buffer> q <Plug>(go-debug-stop)\n  endif\n\n  if has_key(l:debugwindows, \"goroutines\") && l:debugwindows['goroutines'] != ''\n    exe 'silent ' . l:debugwindows['goroutines']\n    silent file `='__GODEBUG_GOROUTINES__'`\n    setlocal buftype=nofile bufhidden=wipe nomodified nobuflisted noswapfile nowrap nonumber nocursorline\n    setlocal filetype=godebugvariables\n    call append(0, [\"# Goroutines\"])\n    nmap <buffer> <silent> <cr> :<c-u>call go#debug#Goroutine()<cr>\n  endif\n\n  if has_key(l:debugwindows, \"out\") && l:debugwindows['out'] != ''\n    exe 'silent ' . l:debugwindows['out']\n    silent file `='__GODEBUG_OUTPUT__'`\n    setlocal buftype=nofile bufhidden=wipe nomodified nobuflisted noswapfile nowrap nonumber nocursorline\n    setlocal filetype=godebugoutput\n    nmap <buffer> q <Plug>(go-debug-stop)\n  endif\n  call win_gotoid(l:winid)\n\n  silent! delcommand GoDebugStart\n  silent! delcommand GoDebugTest\n  silent! delcommand GoDebugTestFunc\n  silent! delcommand GoDebugAttach\n  silent! delcommand GoDebugConnect\n\n  command! -nargs=0 GoDebugContinue   call go#debug#Stack('continue')\n  command! -nargs=0 GoDebugStop       call go#debug#Stop()\n  command! -nargs=0 GoDebugHalt       call go#debug#Stack('halt')\n\n  nnoremap <silent> <Plug>(go-debug-breakpoint) :<C-u>call go#debug#Breakpoint()<CR>\n  nnoremap <silent> <Plug>(go-debug-continue)   :<C-u>call go#debug#Stack('continue')<CR>\n  nnoremap <silent> <Plug>(go-debug-stop)       :<C-u>call go#debug#Stop()<CR>\n\n  call s:restoreMappings()\n  augroup vim-go-debug\n    autocmd! *\n    call s:configureMappings('(go-debug-breakpoint)', '(go-debug-continue)')\n  augroup END\n  doautocmd vim-go-debug BufWinEnter *.go\nendfunction\n\nfunction! s:continue()\n  command! -nargs=0 GoDebugNext       call go#debug#Stack('next')\n  command! -nargs=0 GoDebugStep       call go#debug#Stack('step')\n  command! -nargs=0 GoDebugStepOut    call go#debug#Stack('stepOut')\n  command! -nargs=0 GoDebugRestart    call go#debug#Restart()\n  command! -nargs=* GoDebugSet        call go#debug#Set(<f-args>)\n  command! -nargs=1 GoDebugPrint      call go#debug#Print(<q-args>)\n\n  nnoremap <silent> <Plug>(go-debug-next)       :<C-u>call go#debug#Stack('next')<CR>\n  nnoremap <silent> <Plug>(go-debug-step)       :<C-u>call go#debug#Stack('step')<CR>\n  nnoremap <silent> <Plug>(go-debug-stepout)    :<C-u>call go#debug#Stack('stepOut')<CR>\n  nnoremap <silent> <Plug>(go-debug-print)      :<C-u>call go#debug#Print(expand('<cword>'))<CR>\n  nnoremap <silent> <Plug>(go-debug-halt)       :<C-u>call go#debug#Stack('halt')<CR>\n\n  if has('balloon_eval')\n    let s:balloonexpr=&balloonexpr\n    let s:ballooneval=&ballooneval\n\n    set balloonexpr=go#debug#BalloonExpr()\n    set ballooneval\n  endif\n\n  \" Some debug mappings were already added. Restore any mappings the user had\n  \" before the complete mappings are configured so that the mappings are\n  \" returned to the user's original state after the debugger is stopped.\n  call s:restoreMappings()\n  augroup vim-go-debug\n    autocmd! *\n    call s:configureMappings('(go-debug-breakpoint)', '(go-debug-continue)', '(go-debug-halt)', '(go-debug-next)', '(go-debug-print)', '(go-debug-step)', '(go-debug-stepout)')\n  augroup END\n  doautocmd vim-go-debug BufWinEnter *.go\nendfunction\n\nfunction! s:err_cb(ch, msg) abort\n  if s:isReady()\n    call s:logger('ERR: ', a:ch, a:msg)\n    return\n  endif\n\n  let s:state['message'] += [a:msg]\nendfunction\n\nfunction! s:out_cb(ch, msg) abort\n  if s:isReady()\n    call s:logger('OUT: ', a:ch, a:msg)\n    return\n  endif\n\n  let s:state['message'] += [a:msg]\n\n  if stridx(a:msg, go#config#DebugAddress()) != -1\n    call s:connect(go#config#DebugAddress())\n  endif\nendfunction\n\nfunction! s:connect(addr) abort\n  let s:state['data'] = []\n  let l:state = {'databuf': ''}\n\n  \" explicitly bind callback to state so that within it, self will\n  \" always refer to state. See :help Partial for more information.\n  let l:state.on_data = function('s:on_data', [], l:state)\n\n  if has('nvim')\n    let l:ch = sockconnect('tcp', a:addr, {'on_data': l:state.on_data, 'state': l:state})\n    if l:ch == 0\n      call go#util#EchoError(\"could not connect to debugger\")\n      if has_key(s:state, 'job')\n        call go#job#Stop(s:state['job'])\n      endif\n      return\n    endif\n  else\n    let l:ch = ch_open(a:addr, {'mode': 'raw', 'waittime': 5000, 'timeout': 20000, 'callback': l:state.on_data})\n    if ch_status(l:ch) !=# 'open'\n      call go#util#EchoError(\"could not connect to debugger\")\n      if has_key(s:state, 'job')\n        call go#job#Stop(s:state['job'])\n      endif\n      return\n    endif\n  endif\n\n  let s:state['ch'] = l:ch\n\n  \" Set running so that the next go#debug#Stack call doesn't change operation\n  \" to continue.\n  let s:state['running'] = 0\n\n  \" It is ok to halt whether whether delve was started with connect, debug, or\n  \" test and regardless of whether the the process is already halted.\n  call go#debug#Stack('halt')\n\n  \" Set ready so that breakpoints will be setup and all output from dlv's\n  \" stdout and stderr will be logged.\n  let s:state['ready'] = 1\n\n  call s:sync_breakpoints()\n\n  call s:create_layout()\nendfunction\n\nfunction! s:sync_breakpoints()\n  try\n    \" get the breakpoints\n    call s:call_jsonrpc(function('s:handle_list_breakpoints'), 'RPCServer.ListBreakpoints', {'All': v:true})\n  catch\n    call go#util#EchoError(printf('failed to sync breakpoints (%s): %s', v:throwpoint, v:exception))\n  finally\n  endtry\nendfunction\n\nfunction! s:handle_list_breakpoints(check_errors, res)\n  try\n    call a:check_errors()\n\n    let l:res = a:res\n    if type(l:res) != v:t_dict || !has_key(l:res, 'result') || type(l:res.result) != v:t_dict || !has_key(l:res.result, 'Breakpoints')\n      call go#util#EchoError('could not list breakpoints')\n    endif\n    let l:breakpoints = l:res.result.Breakpoints\n\n    let l:signs = s:list_breakpointsigns()\n\n    \" the breakpoints with a sign\n    let l:signsByBreakpointID = {}\n    \" the signs with a breakpoint\n    let l:breakpointsBySignID = {}\n\n    \" replace the sign when the id of the breakpoint and the sign are\n    \" different\n    for l:sign in l:signs\n      for l:breakpoint in l:breakpoints\n        if l:sign.file == s:substituteRemotePath(l:breakpoint.file) && l:sign.line == l:breakpoint.line\n          if l:sign.id != l:breakpoint.id\n            call s:sign_unplace(l:sign.id, l:sign.file)\n            call s:sign_place(l:breakpoint.id, s:substituteRemotePath(l:breakpoint.file), l:breakpoint.line)\n          endif\n\n          let l:signsByBreakpointID[l:breakpoint.id] = l:sign.id\n          let l:breakpointsBySignID[l:sign.id] = l:breakpoint.id\n          break\n        endif\n      endfor\n    endfor\n\n    \" add a sign for each breakpoint without a sign\n    for l:breakpoint in l:breakpoints\n      if empty(get(l:signsByBreakpointID, l:breakpoint.id, ''))\n        \" ignore breakpoints in files not yet associated with a buffer.\n        let l:localpath = s:substituteRemotePath(l:breakpoint.file)\n        let l:bufname = bufname(fnamemodify(l:localpath, ':.'))\n        if l:bufname is ''\n          continue\n        endif\n\n        call s:sign_place(l:breakpoint.id, l:localpath, l:breakpoint.line)\n      endif\n    endfor\n\n    \" add a breakpoint for each sign without a breakpoint\n    for l:sign in l:signs\n      if empty(get(l:breakpointsBySignID, l:sign.id, ''))\n        let l:promise = go#promise#New(function('s:rpc_response'), 20000, {})\n        call s:call_jsonrpc(l:promise.wrapper, 'RPCServer.CreateBreakpoint', {'Breakpoint': {'file': s:substituteLocalPath(l:sign.file), 'line': l:sign.line}})\n        \"let l:res = l:promise.await()\n      endif\n    endfor\n  catch\n    call go#util#EchoError(printf('failed to sync breakpoints (%s): %s', v:throwpoint, v:exception))\n  finally\n  endtry\nendfunction\n\n\" s:on_data's third optional argument is provided, but not used, so that the\n\" same function can be used for Vim's 'callback' and Neovim's 'data'.\nfunction! s:on_data(ch, data, ...) dict abort\n  let l:data = s:message(self.databuf, a:data)\n\n  let l:messages = split(l:data, \"\\n\")\n  for l:msg in l:messages\n    let l:data = l:messages[0]\n    try\n      let l:res = json_decode(l:data)\n      \" remove the decoded message\n      call remove(l:messages, 0)\n    catch\n      return\n    finally\n      \" Rejoin messages and assign to databuf so that any messages that come\n      \" in if s:handleRPCResult sleeps will be appended correctly.\n      \"\n      \" Because the current message is removed in the try immediately after\n      \" decoding, l:messages contains all the messages that have not yet been\n      \" decoded including the current message if decoding it failed.\n      let self.databuf = join(l:messages, \"\\n\")\n    endtry\n\n    if go#util#HasDebug('debugger-commands')\n      let g:go_debug_commands = add(go#config#DebugCommands(), {\n            \\ 'response': l:res,\n      \\ })\n    endif\n    call s:handleRPCResult(l:res)\n  endfor\nendfunction\n\nfunction! s:message(buf, data) abort\n  if has('nvim')\n    \" dealing with the channel lines of Neovim is awful. The docs (:help\n    \" channel-lines) say:\n    \"     stream event handlers may receive partial (incomplete) lines. For a\n    \"     given invocation of on_stdout etc, `a:data` is not guaranteed to end\n    \"     with a newline.\n    \"       - `abcdefg` may arrive as `['abc']`, `['defg']`.\n    \"       - `abc\\nefg` may arrive as `['abc', '']`, `['efg']` or `['abc']`,\n    \"         `['','efg']`, or even `['ab']`, `['c','efg']`.\n    \"\n    \" Thankfully, though, this is explained a bit better in an issue:\n    \" https://github.com/neovim/neovim/issues/3555. Specifically in these two\n    \" comments:\n    \"     * https://github.com/neovim/neovim/issues/3555#issuecomment-152290804\n    \"     * https://github.com/neovim/neovim/issues/3555#issuecomment-152588749\n    \"\n    \" The key is\n    \"     Every item in the list passed to job control callbacks represents a\n    \"     string after a newline(Except the first, of course). If the program\n    \"     outputs: \"hello\\nworld\" the corresponding list is [\"hello\", \"world\"].\n    \"     If the program outputs \"hello\\nworld\\n\", the corresponding list is\n    \"     [\"hello\", \"world\", \"\"]. In other words, you can always determine if\n    \"     the last line received is complete or not.\n    \" and\n    \"     for every list you receive in a callback, all items except the first\n    \"     represent newlines.\n    let l:data = printf('%s%s', a:buf, a:data[0])\n    for l:msg in a:data[1:]\n      let l:data = printf(\"%s\\n%s\", l:data, l:msg)\n    endfor\n\n    return l:data\n  endif\n\n  return printf('%s%s', a:buf, a:data)\nendfunction\n\n\" s:check_errors will be curried and injected into rpc result handlers so that\n\" those result handlers can consistently check for errors in the response by\n\" catching exceptions and handling the error appropriately.\nfunction! s:check_errors(resp_json) abort\n  if type(a:resp_json) == v:t_dict && has_key(a:resp_json, 'error') && !empty(a:resp_json.error)\n    throw a:resp_json.error\n  endif\nendfunction\n\nfunction! s:handleRPCResult(resp) abort\n  try\n    let l:id = a:resp.id\n    \" call the result handler with its first argument set to a curried\n    \" s:check_errors value so that the result handler can call s:check_errors\n    \" without passing any arguments to check whether the response is an error\n    \" response.\n    call call(s:state.resultHandlers[l:id], [function('s:check_errors', [a:resp]), a:resp])\n  catch\n    throw substitute(v:exception, '^Vim', '', '')\n  finally\n    if has_key(s:state.resultHandlers, l:id)\n      call remove(s:state.resultHandlers, l:id)\n    endif\n  endtry\nendfunction\n\nfunction! go#debug#TestFunc(...) abort\n  let l:test = go#util#TestName()\n  if l:test is ''\n    call go#util#EchoWarning(\"vim-go: [debug] no test found immediate to cursor\")\n    return\n  endif\n  call call('go#debug#Start', extend(['test', '.', '-test.run', printf('%s$', l:test)], a:000))\nendfunction\n\n\" Start the debug mode. The first variadic argument is the package name to\n\" compile and debug, anything else will be passed to the running program.\nfunction! go#debug#Start(mode, ...) abort\n  call go#cmd#autowrite()\n\n  if !go#util#has_job()\n    call go#util#EchoError('This feature requires either Vim 8.0.0087 or newer with +job or Neovim.')\n    return\n  endif\n\n  \" It's already running.\n  if has_key(s:state, 'job')\n    return s:state['job']\n  endif\n\n  let s:start_args = [a:mode] + a:000\n\n  if go#util#HasDebug('debugger-state')\n    call go#config#SetDebugDiag(s:state)\n  endif\n\n  let dlv = go#path#CheckBinPath(\"dlv\")\n  if empty(dlv)\n    return\n  endif\n\n  try\n    if a:mode is 'connect'\n      let l:addr = go#config#DebugAddress()\n      if a:0 > 0\n        let l:addr = a:1\n      endif\n      let s:state['kill_on_detach'] = v:false\n\n      call s:connect(l:addr)\n    else\n      let l:cmd = [dlv, a:mode]\n\n      let s:state['kill_on_detach'] = v:true\n      if a:mode is 'debug' || a:mode is 'test'\n        let l:cmd = extend(l:cmd, s:package(a:000))\n        let l:cmd = extend(l:cmd, ['--output', tempname()])\n      elseif a:mode is 'attach'\n        let l:cmd = add(l:cmd, a:1)\n        let s:state['kill_on_detach'] = v:false\n      else\n        call go#util#EchoError('Unknown dlv command')\n      endif\n\n      let l:cmd += [\n            \\ '--headless',\n            \\ '--api-version', '2',\n            \\ '--listen', go#config#DebugAddress(),\n      \\]\n      let l:debugLogOutput = go#config#DebugLogOutput()\n      if l:debugLogOutput != ''\n        let cmd += ['--log', '--log-output', l:debugLogOutput]\n      endif\n\n      let l:buildtags = go#config#BuildTags()\n      if buildtags isnot ''\n        let l:cmd += ['--build-flags', '--tags=' . buildtags]\n      endif\n\n      if len(a:000) > 1\n        let l:cmd += ['--'] + a:000[1:]\n      endif\n\n      let s:state['message'] = []\n      let l:opts = {\n            \\ 'for': 'GoDebug',\n            \\ 'statustype': 'debug',\n            \\ 'complete': function('s:complete'),\n            \\ }\n      let l:opts = go#job#Options(l:opts)\n      let l:opts.out_cb = function('s:out_cb')\n      let l:opts.err_cb = function('s:err_cb')\n      let l:opts.stoponexit = 'kill'\n\n      let s:state['job'] = go#job#Start(l:cmd, l:opts)\n      return s:state['job']\n    endif\n  catch\n    call go#util#EchoError(printf('could not start debugger: %s', v:exception))\n  endtry\nendfunction\n\n\" s:package returns the import path of package name of a :GoDebug(Start|Test)\n\" call as a list so that the package can be appended to a command list using\n\" extend(). args is expected to be a (potentially empty) list. The first\n\" element in args (if there are any) is expected to be a package path. An\n\" empty list is returned when either args is an empty list or the import path\n\" cannot be determined.\nfunction! s:package(args)\n  if len(a:args) == 0\n    return []\n  endif\n\n  \" append the package when it's given.\n  let l:pkgname = a:args[0]\n  if l:pkgname[0] == '.'\n    let l:pkgabspath = fnamemodify(l:pkgname, ':p')\n\n    let l:dir = go#util#Chdir(expand('%:p:h'))\n    try\n      let l:pkgname = go#package#FromPath(l:pkgabspath)\n      if type(l:pkgname) == type(0)\n        call go#util#EchoError('could not determine package name')\n        return []\n      endif\n    finally\n      call go#util#Chdir(l:dir)\n    endtry\n  endif\n\n  return [l:pkgname]\nendfunction\n\n  \" Translate a reflect kind constant to a human string.\nfunction! s:reflect_kind(k)\n  \" Kind constants from Go's reflect package.\n  return [\n        \\ 'Invalid Kind',\n        \\ 'Bool',\n        \\ 'Int',\n        \\ 'Int8',\n        \\ 'Int16',\n        \\ 'Int32',\n        \\ 'Int64',\n        \\ 'Uint',\n        \\ 'Uint8',\n        \\ 'Uint16',\n        \\ 'Uint32',\n        \\ 'Uint64',\n        \\ 'Uintptr',\n        \\ 'Float32',\n        \\ 'Float64',\n        \\ 'Complex64',\n        \\ 'Complex128',\n        \\ 'Array',\n        \\ 'Chan',\n        \\ 'Func',\n        \\ 'Interface',\n        \\ 'Map',\n        \\ 'Ptr',\n        \\ 'Slice',\n        \\ 'String',\n        \\ 'Struct',\n        \\ 'UnsafePointer',\n  \\ ][a:k]\nendfunction\n\nfunction! s:eval_tree(var, nest, isMapOrSliceChild) abort\n  if a:var.name =~ '^\\~'\n    return ''\n  endif\n  let nest = a:nest\n  let v = ''\n  let kind = s:reflect_kind(a:var.kind)\n\n  if !empty(a:var.name) || a:isMapOrSliceChild is 1\n    if a:isMapOrSliceChild == 0\n      let v .= repeat(' ', nest) . a:var.name . ': '\n    endif\n\n    if kind == 'Bool'\n      let v .= printf(\"%s\", a:var.value)\n\n    elseif kind == 'Struct'\n      \" Anonymous struct\n      if a:var.type[:8] == 'struct { '\n        let v .= printf(\"%s\", a:var.type)\n      else\n        let v .= printf(\"%s{...}\", a:var.type)\n      endif\n\n    elseif kind == 'String'\n      let v .= printf(\"%s[%d]%s\", a:var.type, a:var.len,\n            \\ len(a:var.value) > 0 ? ': ' . a:var.value : '')\n\n    elseif kind == 'Slice' || kind == 'String' || kind == 'Map' || kind == 'Array'\n      let v .= printf(\"%s[%d]\", a:var.type, a:var.len)\n\n    elseif kind == 'Chan' || kind == 'Func' || kind == 'Interface'\n      let v .= printf(\"%s\", a:var.type)\n\n    elseif kind == 'Ptr'\n      \" TODO: We can do something more useful here.\n      let v .= printf(\"%s\", a:var.type)\n\n    elseif kind == 'Complex64' || kind == 'Complex128'\n      let v .= printf(\"%s%s\", a:var.type, a:var.value)\n\n    \" Int, Float\n    else\n      let v .= printf(\"%s(%s)\", a:var.type, a:var.value)\n    endif\n    if a:isMapOrSliceChild == 0\n      let v = printf(\"%s\\n\", v)\n    endif\n  else\n    let nest -= 1\n  endif\n\n  if index(['Chan', 'Complex64', 'Complex128'], kind) == -1 && a:var.type != 'error'\n    let l:idx = 0\n    for c in a:var.children\n      if kind == 'Map'\n        \" Maps alternate children between keys and values. Keys will be even\n        \" number indexes.\n        let l:isMapKey = (l:idx % 2) is 0\n        if l:isMapKey == 1\n          let v .= printf(\"%s%s:\\n\", repeat(' ', nest + 1), s:eval_tree(c, 0, 1))\n        else\n          let v .= printf(\"%s%s\\n\", repeat(' ', nest + 2), s:eval_tree(c, 0, 1))\n        endif\n      elseif kind == 'Slice'\n        let v .= printf(\"%d: %s\\n\", l:idx, s:eval_tree(c, nest + 1, 1))\n      else\n        let v .= s:eval_tree(c, nest + 1, 0)\n      endif\n      let l:idx += 1\n    endfor\n  endif\n  return v\nendfunction\n\nfunction! s:eval(arg) abort\n  try\n    let l:promise = go#promise#New(function('s:rpc_response'), 20000, {})\n    call s:call_jsonrpc(l:promise.wrapper, 'RPCServer.State')\n    let l:res = l:promise.await()\n\n    let l:cmd = 'RPCServer.Eval'\n    let l:args = {\n          \\ 'expr':  a:arg,\n          \\ 'scope': {'GoroutineID': l:res.result.State.currentThread.goroutineID}\n      \\ }\n\n    let l:ResultFn = funcref('s:evalResult', [])\n    if a:arg =~ '^call '\n      let l:cmd = 'RPCServer.Command'\n      let l:args = {\n            \\ 'name': 'call',\n            \\ 'Expr': a:arg[5:],\n            \\ 'ReturnInfoLoadConfig': {\n              \\ 'FollowPointers': v:false,\n              \\ 'MaxVariableRecurse': 10,\n              \\ 'MaxStringLen': 80,\n              \\ 'MaxArrayValues': 10,\n              \\ 'MaxStructFields': 10,\n            \\ },\n          \\ }\n\n      let l:ResultFn = funcref('s:callResult', [])\n    endif\n\n    let l:promise = go#promise#New(function('s:rpc_response'), 20000, {})\n    call s:call_jsonrpc(l:promise.wrapper, l:cmd, l:args)\n\n    let l:res = l:promise.await()\n\n    let l:result = call(l:ResultFn, [l:res.result])\n\n    \" l:result will be a list when evaluating a call expression.\n    if type(l:result) is type([])\n      let l:result = map(l:result, funcref('s:renameEvalReturnValue'))\n      if len(l:result) isnot 1\n        return map(l:result, 's:eval_tree(v:val, 0, 0)')\n      endif\n      let l:result = l:result[0]\n    endif\n    return s:eval_tree(l:result, 0, 0)\n  catch\n    call go#util#EchoError(printf('evaluation failed: %s', v:exception))\n    return ''\n  endtry\nendfunction\n\nfunction! s:callResult(res) abort\n  return a:res.State.currentThread.ReturnValues\nendfunction\n\nfunction! s:evalResult(res) abort\n  return a:res.Variable\nendfunction\n\nfunction! s:renameEvalReturnValue(key, val) abort\n  let a:val.name = printf('[%s]', string(a:key))\n  return a:val\nendfunction\n\nfunction! go#debug#BalloonExpr() abort\n  silent! let l:v = s:eval(v:beval_text)\n  return l:v\nendfunction\n\nfunction! go#debug#Print(arg) abort\n  try\n    let l:result = s:eval(a:arg)\n    if type(l:result) is type([])\n      echo join(map(l:result, 'substitute(v:val, \"\\n$\", \"\", '''')'), \"\\n\")\n      return\n    elseif type(l:result) isnot type('')\n      throw 'unexpected result'\n    endif\n    echo substitute(l:result, \"\\n$\", \"\", '')\n  catch\n    call go#util#EchoError(printf('could not print: %s', v:exception))\n  endtry\nendfunction\n\nfunction! s:update_goroutines() abort\n  call s:call_jsonrpc(function('s:update_goroutines_state_handler'), 'RPCServer.State')\nendfunction\n\nfunction! s:update_goroutines_state_handler(check_errors, res) abort\n  try\n    call a:check_errors()\n\n    let l:currentGoroutineID = 0\n    try\n      if type(a:res) is type({}) && has_key(a:res, 'result') && !empty(a:res['result'])\n        let l:currentGoroutineID = a:res[\"result\"][\"State\"][\"currentGoroutine\"][\"id\"]\n      endif\n    catch\n      call go#util#EchoWarning(\"current goroutine not found...\")\n    endtry\n\n    call s:call_jsonrpc(function('s:list_goroutines_handler', [l:currentGoroutineID]), 'RPCServer.ListGoroutines')\n  catch\n    call go#util#EchoError(printf('could not list goroutines: %s', v:exception))\n  endtry\nendfunction\n\nfunction s:list_goroutines_handler(currentGoroutineID, check_errors, res) abort\n  try\n    call a:check_errors()\n    call s:show_goroutines(a:currentGoroutineID, a:res)\n  catch\n    call go#util#EchoError(printf('could not show goroutines: %s', v:exception))\n  endtry\nendfunction\n\nfunction! s:show_goroutines(currentGoroutineID, res) abort\n  let l:goroutines_winid = bufwinid('__GODEBUG_GOROUTINES__')\n  if l:goroutines_winid == -1\n    return\n  endif\n\n  let l:winid = win_getid()\n  call win_gotoid(l:goroutines_winid)\n\n  try\n    setlocal modifiable\n    silent %delete _\n\n    let v = []\n\n    if type(a:res) isnot type({}) || !has_key(a:res, 'result') || empty(a:res['result'])\n      call setline(1, v)\n      return\n    endif\n\n    let l:goroutines = a:res[\"result\"][\"Goroutines\"]\n    if len(l:goroutines) == 0\n      call go#util#EchoWarning(\"No Goroutines Running Now...\")\n      call setline(1, v)\n      return\n    endif\n\n    let l:currentGoroutine = []\n    for l:idx in range(len(l:goroutines))\n      let l:goroutine = l:goroutines[l:idx]\n      let l:goroutineType = \"\"\n      let l:loc = 0\n      if l:goroutine.startLoc.file != \"\"\n          let l:loc = l:goroutine.startLoc\n          let l:goroutineType = \"Start\"\n      endif\n      if l:goroutine.goStatementLoc.file != \"\"\n          let l:loc = l:goroutine.goStatementLoc\n          let l:goroutineType = \"Go\"\n      endif\n      if l:goroutine.currentLoc.file != \"\"\n          let l:loc = l:goroutine.currentLoc\n          let l:goroutineType = \"Runtime\"\n      endif\n      if l:goroutine.userCurrentLoc.file != \"\"\n          let l:loc=l:goroutine.userCurrentLoc\n          let l:goroutineType = \"User\"\n      endif\n\n      \" The current goroutine can be changed by pressing enter on one of the\n      \" lines listing a non-active goroutine. If the format of either of these\n      \" lines is modified, then make sure that go#debug#Goroutine is also\n      \" changed if needed.\n      if l:goroutine.id == a:currentGoroutineID\n        let l:g = printf(\"* Goroutine %s - %s: %s:%s %s (thread: %s)\", l:goroutine.id, l:goroutineType, s:substituteRemotePath(l:loc.file), l:loc.line, l:loc.function.name, l:goroutine.threadID)\n        let l:currentGoroutine = [l:g]\n        continue\n      else\n        let l:g = printf(\"  Goroutine %s - %s: %s:%s %s (thread: %s)\", l:goroutine.id, l:goroutineType, s:substituteRemotePath(l:loc.file), l:loc.line, l:loc.function.name, l:goroutine.threadID)\n      endif\n      let v += [l:g]\n    endfor\n\n    let v = ['# Goroutines'] + l:currentGoroutine + v\n\n    call setline(1, v)\n  finally\n    setlocal nomodifiable\n    call win_gotoid(l:winid)\n  endtry\nendfunction\n\nfunction! s:update_variables() abort\n  \" FollowPointers requests pointers to be automatically dereferenced.\n  \" MaxVariableRecurse is how far to recurse when evaluating nested types.\n  \" MaxStringLen is the maximum number of bytes read from a string\n  \" MaxArrayValues is the maximum number of elements read from an array, a slice or a map.\n  \" MaxStructFields is the maximum number of fields read from a struct, -1 will read all fields.\n  let l:cfg = {\n        \\ 'scope': {'GoroutineID': s:goroutineID()},\n        \\ 'cfg':   {'MaxStringLen': 20, 'MaxArrayValues': 20, 'MaxVariableRecurse': 10}\n        \\ }\n\n  try\n    call s:call_jsonrpc(function('s:handle_list_local_vars'), 'RPCServer.ListLocalVars', l:cfg)\n  catch\n    call go#util#EchoError(printf('could not list variables: %s', v:exception))\n  endtry\n\n  try\n    call s:call_jsonrpc(function('s:handle_list_function_args'), 'RPCServer.ListFunctionArgs', l:cfg)\n  catch\n    call go#util#EchoError(printf('could not list function arguments: %s', v:exception))\n  endtry\n\n  try\n    call s:call_jsonrpc(function('s:handle_list_registers'), 'RPCServer.ListRegisters', l:cfg)\n  catch\n    call go#util#EchoError(printf('could not list registers: %s', v:exception))\n  endtry\n\nendfunction\n\nfunction! s:handle_list_local_vars(check_errors, res) abort\n  let s:state['localVars'] = {}\n  try\n    call a:check_errors()\n    if type(a:res) is type({}) && has_key(a:res, 'result') && !empty(a:res.result)\n      let s:state['localVars'] = a:res.result['Variables']\n    endif\n  catch\n    call go#util#EchoWarning(printf('could not list variables: %s', v:exception))\n  endtry\n\n  call s:show_variables()\nendfunction\n\nfunction! s:handle_list_function_args(check_errors, res) abort\n  let s:state['functionArgs'] = {}\n  try\n    call a:check_errors()\n    if type(a:res) is type({}) && has_key(a:res, 'result') && !empty(a:res.result)\n      let s:state['functionArgs'] = a:res.result['Args']\n    endif\n  catch\n    call go#util#EchoWarning(printf('could not list function arguments: %s', v:exception))\n  endtry\n\n  call s:show_variables()\nendfunction\n\nfunction! s:handle_list_registers(check_errors, res) abort\n  let s:state['registers'] = {}\n  try\n    call a:check_errors()\n    if type(a:res) is type({}) && has_key(a:res, 'result') && !empty(a:res.result)\n      let s:state['registers'] = a:res.result['Regs']\n    endif\n  catch\n    call go#util#EchoWarning(printf('could not list registers: %s', v:exception))\n  endtry\n\n  call s:show_variables()\nendfunction\n\nfunction! go#debug#Set(symbol, value) abort\n  try\n    let l:promise = go#promise#New(function('s:rpc_response'), 20000, {})\n    call s:call_jsonrpc(l:promise.wrapper, 'RPCServer.State')\n    let l:res = l:promise.await()\n\n    call s:call_jsonrpc(function('s:handle_set'), 'RPCServer.Set', {\n          \\ 'symbol': a:symbol,\n          \\ 'value':  a:value,\n          \\ 'scope':  {'GoroutineID': l:res.result.State.currentThread.goroutineID}\n    \\ })\n  catch\n    call go#util#EchoError(printf('could not set symbol value: %s', v:exception))\n  endtry\n\n  call s:update_variables()\nendfunction\n\nfunction! s:handle_set(check_errors, res) abort\n  try\n    call a:check_errors()\n  catch\n    call go#util#EchoError(printf('could not set symbol value: %s', v:exception))\n  endtry\n\n  call s:update_variables()\nendfunction\n\nfunction! s:update_stacktrace() abort\n  try\n    call s:call_jsonrpc(function('s:show_stacktrace'), 'RPCServer.Stacktrace', {'id': s:goroutineID(), 'depth': 5})\n  catch\n    call go#util#EchoError(printf('could not update stack: %s', v:exception))\n  endtry\nendfunction\n\nfunction! s:update_windows(res) abort\n  let s:stack_name = ''\n\n  if type(a:res) isnot type({}) || !has_key(a:res, 'result') || empty(a:res.result)\n    return\n  endif\n\n  if s:exited(a:res)\n    call go#debug#Stop()\n    return\n  endif\n  call s:update_breakpoint(a:res)\n  call s:update_goroutines()\n  call s:update_stacktrace()\n  call s:update_variables()\nendfunction\n\n\" Send a command to change the cursor location to Delve.\n\"\n\" a:name must be one of continue, next, step, or stepOut.\nfunction! go#debug#Stack(name) abort\n  let l:name = a:name\n\n  \" Run continue if the program hasn't started yet.\n  if s:state.running is 0\n    if l:name != 'halt'\n      let l:name = 'continue'\n      let s:state.running = 1\n      call s:continue()\n    endif\n  endif\n\n  \" Add a breakpoint to the main.Main if the user didn't define any.\n  \" TODO(bc): actually set the breakpoint in main.Main\n  if len(s:list_breakpointsigns()) is 0\n    if go#debug#Breakpoint() isnot 0\n      let s:state.running = 0\n      return\n    endif\n  endif\n\n  try\n    \" s:stack_name is reset in s:update_windows(). While its value is 'next', the\n    \" current operation being performed by delve is a next operation and it\n    \" must be cancelled before another next operation can start. See\n    \" https://github.com/go-delve/delve/blob/ab5713d3ec5d12754f4b2edf85e4b36a08b67c48/Documentation/api/ClientHowto.md#special-continue-commands-and-asynchronous-breakpoints\n    \" for more information.\n    if l:name is# 'next' && get(s:, 'stack_name', '') is# 'next'\n      \" use s:rpc_response so that the any errors will be checked instead of\n      \" completely discarding the result with s:noop.\n      let l:promise = go#promise#New(function('s:rpc_response'), 20000, {})\n      call s:call_jsonrpc(l:promise.wrapper, 'RPCServer.CancelNext')\n      call l:promise.await()\n    endif\n    let s:stack_name = l:name\n    try\n      silent! sign unplace 9999\n      call s:call_jsonrpc(function('s:handle_stack_response', [l:name]), 'RPCServer.Command', {'name': l:name})\n    catch\n      call go#util#EchoError(printf('rpc failure: %s', v:exception))\n      call s:clearState()\n      call go#util#EchoInfo('restarting debugger')\n      call go#debug#Restart()\n    endtry\n  catch\n    call go#util#EchoError(printf('CancelNext RPC call failed: %s', v:exception))\n  endtry\nendfunction\n\nfunction! s:handle_stack_response(command, check_errors, res) abort\n  try\n    call a:check_errors()\n\n    if s:state.running is 0 && a:command is# 'halt'\n      return\n    endif\n\n    if a:command is# 'next'\n      call s:handleNextInProgress(a:res)\n    endif\n\n    call s:update_windows(a:res)\n  catch\n    call go#util#EchoError(printf('rpc failure: %s', v:exception))\n    call s:clearState()\n    call go#util#EchoInfo('restarting debugger')\n    call go#debug#Restart()\n  endtry\nendfunction\n\nfunction! s:handleNextInProgress(res)\n  try\n    let l:res = a:res\n    let l:w = 0\n    while l:w < 1\n      if l:res.result.State.NextInProgress == v:true\n        \" TODO(bc): message the user that a breakpoint was hit in a different\n        \" goroutine while trying to resume.\n        let l:promise = go#promise#New(function('s:rpc_response'), 20000, {})\n        call s:call_jsonrpc(l:promise.wrapper, 'RPCServer.Command', {'name': 'continue'})\n        let l:res = l:promise.await()\n      else\n        return\n      endif\n    endwhile\n  catch\n    throw substitute(v:exception, '^Vim', '', '')\n  endtry\nendfunction\n\nfunction! go#debug#Restart() abort\n  call go#cmd#autowrite()\n\n  try\n    call s:restoreMappings()\n    call s:stop()\n\n    let s:state = {\n          \\ 'rpcid': 0,\n          \\ 'running': 0,\n          \\ 'currentThread': {},\n          \\ 'localVars': {},\n          \\ 'functionArgs': {},\n          \\ 'registers': {},\n          \\ 'message': [],\n          \\ 'resultHandlers': {},\n          \\ 'kill_on_detach': s:state['kill_on_detach'],\n        \\ }\n\n    call call('go#debug#Start', s:start_args)\n  catch\n    call go#util#EchoError(printf('restart failed: %s', v:exception))\n  endtry\nendfunction\n\n\" Report if debugger mode is ready.\nfunction! s:isReady()\n  return get(s:state, 'ready', 0) != 0\nendfunction\n\n\" Change Goroutine\nfunction! go#debug#Goroutine() abort\n  let l:goroutineID = str2nr(substitute(getline('.'), '^  Goroutine \\(.\\{-1,\\}\\) - .*', '\\1', 'g'))\n\n  if l:goroutineID <= 0\n    return\n  endif\n\n  try\n    let l:promise = go#promise#New(function('s:rpc_response'), 20000, {})\n    call s:call_jsonrpc(l:promise.wrapper, 'RPCServer.Command', {'Name': 'switchGoroutine', 'GoroutineID': l:goroutineID})\n    let l:res = l:promise.await()\n    call s:update_windows(l:res)\n    call go#util#EchoInfo(\"Switched goroutine to: \" . l:goroutineID)\n  catch\n    call go#util#EchoError(printf('could not switch goroutine: %s', v:exception))\n  endtry\nendfunction\n\n\" Toggle breakpoint. Returns 0 on success and 1 on failure.\nfunction! go#debug#Breakpoint(...) abort\n  let l:filename = fnamemodify(expand('%'), ':p:gs!\\\\!/!')\n  let l:linenr = line('.')\n\n  \" Get line number from argument.\n  if len(a:000) > 0\n    let l:linenr = str2nr(a:1)\n    if l:linenr is 0\n      call go#util#EchoError('not a number: ' . a:1)\n      return 0\n    endif\n    if len(a:000) > 1\n      let l:filename = a:2\n    endif\n  endif\n\n  try\n    \" Check if we already have a breakpoint for this line.\n    let l:found = {}\n    for l:bt in s:list_breakpointsigns()\n      if l:bt.file is# l:filename && l:bt.line is# l:linenr\n        let l:found = l:bt\n        break\n      endif\n    endfor\n\n    \" Remove breakpoint.\n    if type(l:found) == v:t_dict && !empty(l:found)\n      call s:sign_unplace(l:found.id, l:found.file)\n      if s:isReady()\n        let l:promise = go#promise#New(function('s:rpc_response'), 20000, {})\n        call s:call_jsonrpc(l:promise.wrapper, 'RPCServer.ClearBreakpoint', {'id': l:found.id})\n        let res = l:promise.await()\n      endif\n    else \" Add breakpoint\n      if s:isReady()\n        let l:promise = go#promise#New(function('s:rpc_response'), 20000, {})\n        call s:call_jsonrpc(l:promise.wrapper, 'RPCServer.CreateBreakpoint', {'Breakpoint': {'file': s:substituteLocalPath(l:filename), 'line': l:linenr}})\n        let l:res = l:promise.await()\n        let l:bt = l:res.result.Breakpoint\n        call s:sign_place(l:bt.id, s:substituteRemotePath(l:bt.file), l:bt.line)\n      else\n        let l:id = len(s:list_breakpointsigns()) + 1\n        call s:sign_place(l:id, l:filename, l:linenr)\n      endif\n    endif\n  catch\n    call go#util#EchoError(printf('could not toggle breakpoint: %s', v:exception))\n    return 1\n  endtry\n\n  return 0\nendfunction\n\nfunction! s:sign_unplace(id, file) abort\n  if !exists('*sign_unplace')\n    exe 'sign unplace ' . a:id .' file=' . a:file\n    return\n  endif\n\n  call sign_unplace('vim-go-debug', {'buffer': a:file, 'id': a:id})\nendfunction\n\nfunction! s:sign_place(id, expr, lnum) abort\n  \" Check if lnum is less than 1 or expr is empty or null\n  if a:lnum < 1 || empty(a:expr)\n    return\n  endif\n\n  if !exists('*sign_place')\n    exe 'sign place ' . a:id . ' line=' . a:lnum . ' name=godebugbreakpoint file=' . a:expr\n    return\n  endif\n\n  call sign_place(a:id, 'vim-go-debug', 'godebugbreakpoint', a:expr, {'lnum': a:lnum})\nendfunction\n\nfunction! s:list_breakpointsigns()\n  let l:breakpoints = []\n  let l:signs = s:sign_getplaced()\n  for l:item in l:signs\n    let l:file = fnamemodify(bufname(l:item.bufnr), ':p')\n    for l:sign in l:item.signs\n      \" ignore the current location sign\n      if l:sign.id is 9999\n        continue\n      endif\n      call add(l:breakpoints, {\n            \\ 'id': l:sign.id,\n            \\ 'file': l:file,\n            \\ 'line': l:sign.lnum,\n      \\ })\n    endfor\n  endfor\n\n  return l:breakpoints\nendfunction\n\nfunction! s:sign_getplaced() abort\n  if !exists('*sign_getplaced') \" sign_getplaced was introduced in Vim 8.1.0614\n    \" :sign place\n    \" --- Signs ---\n    \" Signs for a.go:\n    \"     line=15  id=2  name=godebugbreakpoint\n    \"     line=16  id=1  name=godebugbreakpoint\n    \" Signs for a_test.go:\n    \"     line=6  id=3  name=godebugbreakpoint\n\n    \" l:signs should be the same sam form as the return  value for\n    \" sign_getplaced(), a list with the following entries:\n    \"   * bufnr - number of the buffer with the sign\n    \"   * signs = list of signs placed in bufnr\n    let l:signs = []\n    let l:file = ''\n    for l:line in split(execute('sign place'), '\\n')[1:]\n      if l:line =~# '^Signs for '\n        let l:file = l:line[10:-2]\n        continue\n      else\n        \" sign place's output may end with Signs instead of starting with Signs.\n        \" See\n        \" https://github.com/fatih/vim-go/issues/2920#issuecomment-644885774.\n        let l:idx = match(l:line, '\\.go .* Signs:$')\n        if l:idx >= 0\n          let l:file = l:line[0:l:idx+2]\n          continue\n        endif\n      endif\n\n      if l:line !~# 'name=godebugbreakpoint'\n        continue\n      endif\n\n      let l:sign = matchlist(l:line, '\\vline\\=(\\d+) +id\\=(\\d+)')\n      call add(l:signs, {\n                          \\ 'bufnr': bufnr(l:file),\n                          \\ 'signs': [{\n                            \\ 'id': str2nr(l:sign[2]),\n                            \\ 'lnum': str2nr(l:sign[1]),\n                          \\ }],\n                      \\ })\n    endfor\n\n    return l:signs\n  endif\n\n  \" it would be nice to use lambda's here, but vim-vimparser currently fails\n  \" to parse lamdas as map() arguments.\n  \" TODO(bc): return flatten(map(filter(copy(getbufinfo()), { _, val -> val.listed }), { _, val -> sign_getplaced(val.bufnr, {'group': 'vim-go-debug', 'name': 'godebugbreakpoint'})}))\n  let l:bufinfo = getbufinfo()\n  let l:listed = []\n  for l:info in l:bufinfo\n    if l:info.listed\n      let l:listed = add(l:listed, l:info)\n    endif\n  endfor\n\n  let l:signs = []\n  for l:buf in l:listed\n    let l:signs = add(l:signs, sign_getplaced(l:buf.bufnr, {'group': 'vim-go-debug', 'name': 'godebugbreakpoint'})[0])\n  endfor\n  return l:signs\nendfunction\n\nexe 'sign define godebugbreakpoint text='.go#config#DebugBreakpointSignText().' texthl=GoDebugBreakpoint'\nsign define godebugcurline    text== texthl=GoDebugCurrent    linehl=GoDebugCurrent\n\n\" s:rpc_response is a convenience function to check for errors and return\n\" a:res when a:res is not an error response.\nfunction! s:rpc_response(check_errors, res) abort\n  call a:check_errors()\n  return a:res\nendfunction\n\n\" s:noop is a noop function. It takes any number of arguments and does\n\" nothing.\nfunction s:noop(...) abort\nendfunction\n\nfunction! s:warn_when_stale(filename) abort\n  let l:bufinfo = getbufinfo(a:filename)\n  if len(l:bufinfo) == 0\n    return\n  endif\n\n  if l:bufinfo[0].changed\n    call s:warn_stale()\n    return\n  endif\n\n  call s:call_jsonrpc(function('s:handle_staleness_check_response', [fnamemodify(a:filename, ':p')]), 'RPCServer.LastModified')\nendfunction\n\nfunction! s:handle_staleness_check_response(filename, check_errors, res) abort\n  try\n    call a:check_errors()\n  catch\n    \" swallow any errors\n    return\n  endtry\n\n  let l:ftime = strftime('%Y-%m-%dT%H:%M:%S', getftime(a:filename))\n  if l:ftime < a:res.result.Time[0:(len(l:ftime) - 1)]\n    return\n  endif\n  call s:warn_stale(a:filename)\nendfunction\n\nfunction! s:warn_stale(filename) abort\n  call go#util#EchoWarning(printf('file locations may be incorrect, because %s has changed since debugging started', a:filename))\nendfunction\n\n\nfunction! s:configureMappings(...) abort\n  if a:0 == 0\n    return\n  endif\n\n  let l:debug_mappings = go#config#DebugMappings()\n\n  for l:arg in a:000\n    if !has_key(l:debug_mappings, l:arg)\n      continue\n    endif\n\n    let l:config = l:debug_mappings[l:arg]\n\n    \" do not attempt to apply the mapping when the key is empty or missing.\n    if get(l:config, 'key', '') == ''\n      continue\n    endif\n\n    let l:lhs = l:config.key\n    try\n      call execute(printf('autocmd BufWinEnter *.go call s:save_maparg_for(expand(''%%''), ''%s'')', l:lhs))\n      call execute('autocmd BufWinLeave  *.go call s:restoreMappings()')\n\n      let l:mapping = 'autocmd BufWinEnter *.go nmap <buffer>'\n      if has_key(l:config, 'arguments')\n        let l:mapping = printf('%s %s', l:mapping, l:config.arguments)\n      endif\n      let l:mapping = printf('%s %s <Plug>%s', l:mapping, l:lhs, l:arg)\n      call execute(l:mapping)\n    catch\n      call go#util#EchoError(printf('could not configure mapping for %s: %s', l:lhs, v:exception))\n    endtry\n  endfor\nendfunction\n\nfunction! s:save_maparg_for(bufname, lhs) abort\n  \" make sure bufname is the active buffer.\n  if fnamemodify(a:bufname, ':p') isnot expand('%:p')\n    call go#util#EchoWarning('buffer must be active to save its mappings')\n    return\n  endif\n\n  \" only normal-mode buffer-local mappings are needed, because all\n  \" vim-go-debug mappings are normal-mode buffer-local mappings. Therefore,\n  \" we only need to retrieve normal mode mappings that need to be saved.\n  let l:maparg = maparg(a:lhs, 'n', 0, 1)\n  if empty(l:maparg)\n    return\n  endif\n\n  if l:maparg.buffer\n    let l:bufmapargs = get(s:mapargs, a:bufname, [])\n    let l:bufmapargs = add(l:bufmapargs, l:maparg)\n    let s:mapargs[a:bufname] = l:bufmapargs\n  endif\nendfunction\n\nfunction! s:restoreMappings() abort\n  \" Remove all debugging mappings.\n  for l:mapping in values(go#config#DebugMappings())\n    let l:lhs = get(l:mapping, 'key', '')\n    if l:lhs == ''\n      continue\n    endif\n    let l:maparg = maparg(l:lhs, 'n', 0, 1)\n    if empty(l:maparg)\n      continue\n    endif\n    if l:maparg.buffer\n      call execute(printf('nunmap <buffer> %s', l:lhs))\n    endif\n  endfor\n\n  call s:restoremappingfor(bufname(''))\nendfunction\n\nfunction! s:restoremappingfor(bufname) abort\n  if !has_key(s:mapargs, a:bufname)\n    return\n  endif\n\n  for l:maparg in s:mapargs[a:bufname]\n    call s:restore_mapping(l:maparg)\n  endfor\n  call remove(s:mapargs, a:bufname)\nendfunction\n\nfunction! s:restore_mapping(maparg)\n  if empty(a:maparg)\n    return\n  endif\n  if !exists('*mapset')\n    \" see :h :map-arguments\n    let l:silent_attr = get(a:maparg, 'silent',  0) ? '<silent>' : ''\n    let l:nowait_attr = get(a:maparg, 'no_wait', 0) ? '<nowait>' : ''\n    let l:buffer_attr = get(a:maparg, 'buffer',  0) ? '<buffer>' : ''\n    let l:expr_attr   = get(a:maparg, 'expr',    0) ? '<expr>'   : ''\n    let l:unique_attr = get(a:maparg, 'unique',  0) ? '<unique>' : ''\n    let l:script_attr = get(a:maparg, 'script',  0) ? '<script>' : ''\n\n    let l:command     = [a:maparg['mode'], (get(a:maparg, 'noremap', 0) ? 'nore' : ''), 'map']\n    let l:command     = join(filter(l:command, '!empty(v:val)'), '')\n    let l:rhs         = a:maparg['rhs']\n    let l:lhs         = a:maparg['lhs']\n\n    \" NOTE: most likely <buffer> should be first\n    let l:mapping = join(filter([l:command, l:buffer_attr, l:silent_attr, l:nowait_attr, l:expr_attr, l:unique_attr, l:script_attr, l:lhs, l:rhs], '!empty(v:val)'))\n    call execute(l:mapping)\n    return\n  endif\n\n  call mapset('n', 0, a:maparg)\n  return\nendfunction\n\nfunction! s:substituteRemotePath(path) abort\n  return s:substitutePath(a:path, go#config#DebugSubstitutePaths())\nendfunction\n\nfunction! s:substituteLocalPath(path) abort\n  return s:substitutePath(a:path, map(deepcopy(go#config#DebugSubstitutePaths()), '[v:val[1], v:val[0]]'))\nendfunction\n\nfunction! s:substitutePath(path, substitutions) abort\n  for [l:from, l:to] in a:substitutions\n    if len(a:path) < len(l:from)\n      continue\n    endif\n    if a:path[0:len(l:from)-1] != l:from\n      continue\n    endif\n\n    return printf('%s%s', l:to, a:path[len(l:from):-1])\n  endfor\n\n  return a:path\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/debug_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! Test_GoDebugStart_Empty() abort\n  call s:debug()\nendfunction\n\nfunction! Test_GoDebugStart_RelativePackage() abort\n  call s:debug('./debug/debugmain')\nendfunction\n\nfunction! Test_GoDebugStart_RelativePackage_NullModule() abort\n  call s:debug('./debug/debugmain', 1)\nendfunction\n\nfunction! Test_GoDebugStart_Package() abort\n  call s:debug('vim-go.test/debug/debugmain')\nendfunction\n\nfunction! Test_GoDebugStart_Errors() abort\n  if !go#util#has_job()\n    return\n  endif\n\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let l:tmp = gotest#load_fixture('debug/compilerror/main.go')\n\n    let l:expected = [\n          \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 0, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': '# vim-go.test/debug/compilerror'},\n          \\ {'lnum': 6, 'bufnr': bufnr('%'), 'col': 22, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': ' syntax error: unexpected newline in argument list; possibly missing comma or )'},\n          \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 0, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'exit status 1'}\n          \\]\n  let [l:goversion, l:err] = go#util#Exec(['go', 'env', 'GOVERSION'])\n  let l:goversion = split(l:goversion, \"\\n\")[0]\n\"  if l:goversion < 'go1.20'\n\"    let expected = [\n\"          \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 0, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': '# vim-go.test/debug/compilerror'},\n\"          \\ {'lnum': 6, 'bufnr': bufnr('%'), 'col': 22, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': ' syntax error: unexpected newline in argument list; possibly missing comma or )'},\n\"          \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 0, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'exit status 2'}\n\"        \\ ]\n\"  endif\n    call setqflist([], 'r')\n\n    call assert_false(exists(':GoDebugStop'))\n\n    call go#util#Chdir('debug/compilerror')\n\n    call go#debug#Start('debug')\n\n    let l:actual = getqflist()\n    let l:start = reltime()\n    while len(l:actual) == 0 && reltimefloat(reltime(l:start)) < 10\n      sleep 100m\n      let l:actual = getqflist()\n    endwhile\n\n    call gotest#assert_quickfix(l:actual, l:expected)\n    call assert_false(exists(':GoDebugStop'))\n\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n    \" clear the quickfix lists\n    call setqflist([], 'r')\n  endtry\nendfunction\n\nfunction! Test_GoDebugModeRemapsAndRestoresKeys() abort\n  if !go#util#has_job()\n    return\n  endif\n\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let g:go_debug_mappings = {'(go-debug-continue)': {'key': 'q', 'arguments': '<nowait>'}}\n    let l:tmp = gotest#load_fixture('debug/debugmain/debugmain.go')\n\n    call assert_false(exists(':GoDebugStop'))\n\n    call go#util#Chdir('debug/debugmain')\n\n    call go#debug#Start('debug')\n\n    let l:start = reltime()\n    while maparg('q') == '' && reltimefloat(reltime(l:start)) < 10\n      sleep 100m\n    endwhile\n\n    call assert_false(exists(':GoDebugStart'))\n    call assert_equal('<Plug>(go-debug-continue)', maparg('q', 'n', 0))\n\n    call go#debug#Stop()\n    while exists(':GoDebugStop') && reltimefloat(reltime(l:start)) < 10\n      sleep 100m\n    endwhile\n    call assert_equal('', maparg('q'))\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunction\n\nfunction! Test_GoDebugStopRemovesPlugMappings() abort\n  if !go#util#has_job()\n    return\n  endif\n\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let l:tmp = gotest#load_fixture('debug/debugmain/debugmain.go')\n\n    call assert_false(exists(':GoDebugStop'))\n\n    call go#util#Chdir('debug/debugmain')\n\n    call go#debug#Start('debug')\n\n    let l:start = reltime()\n    while maparg('<Plug>(go-debug-stop)') == '' && reltimefloat(reltime(l:start)) < 10\n      sleep 100m\n    endwhile\n\n    call assert_false(exists(':GoDebugStart'))\n    call assert_equal(':<C-U>call go#debug#Stop()<CR>', maparg('<Plug>(go-debug-stop)', 'n', 0))\n\n    call go#debug#Stop()\n    while exists(':GoDebugStop') && reltimefloat(reltime(l:start)) < 10\n      sleep 100m\n    endwhile\n    call assert_equal('', maparg('<Plug>(go-debug-stop'))\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunction\n\n\" s:debug takes 2 optional arguments. The first is a package to debug. The\n\" second is a flag to indicate whether to reset GOPATH after\n\" gotest#load_fixture is called in order to test behavior outside of GOPATH.\nfunction! s:debug(...) abort\n  if !go#util#has_job()\n    return\n  endif\n\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let $oldgopath = $GOPATH\n    let l:tmp = gotest#load_fixture('debug/debugmain/debugmain.go')\n\n    if a:0 > 1 && a:2 == 1\n      let $GOPATH = $oldgopath\n    endif\n\n    call go#debug#Breakpoint(6)\n\n    call assert_false(exists(':GoDebugStop'))\n\n    if a:0 == 0\n      call go#util#Chdir(printf('%s/src/debug/debugmain', l:tmp))\n      let l:job = go#debug#Start('debug')\n    else\n      let l:job = go#debug#Start('debug', a:1)\n    endif\n\n    let l:start = reltime()\n    while !exists(':GoDebugStop') && reltimefloat(reltime(l:start)) < 10\n      sleep 100m\n    endwhile\n\n    call assert_true(exists(':GoDebugStop'))\n    call gotest#assert_quickfix(getqflist(), [])\n\n    call go#debug#Stop()\n\n    if !has('nvim')\n      call assert_equal(job_status(l:job), 'dead')\n    endif\n\n    call assert_false(exists(':GoDebugStop'))\n\n  finally\n    call go#debug#Breakpoint(6)\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/decls.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! go#decls#Decls(mode, ...) abort\n  let decls_mode = go#config#DeclsMode()\n  if decls_mode == 'ctrlp'\n    call ctrlp#init(call(\"ctrlp#decls#cmd\", [a:mode] + a:000))\n  elseif decls_mode == 'fzf'\n    call call(\"fzf#decls#cmd\", [a:mode] + a:000)\n  else\n    if globpath(&rtp, 'plugin/ctrlp.vim') != \"\"\n      call ctrlp#init(call(\"ctrlp#decls#cmd\", [a:mode] + a:000))\n    elseif globpath(&rtp, 'plugin/fzf.vim') != \"\"\n      call call(\"fzf#decls#cmd\", [a:mode] + a:000)\n    else\n      call go#util#EchoError(\"neither ctrlp.vim nor fzf.vim are installed. Please install either one\")\n    end\n  end\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/def.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nlet s:go_stack = []\nlet s:go_stack_level = 0\n\n\" go#def#Jump jumps to a definition. Valid modes are 'tab', 'split', 'vsplit',\n\" and the empty string, ''.\nfunction! go#def#Jump(mode, type) abort\n  let l:fname = fnamemodify(expand(\"%\"), ':p:gs?\\\\?/?')\n\n  let bin_name = go#config#DefMode()\n  if bin_name == 'godef'\n    let l:cmd = ['godef',\n          \\ '-f=' . l:fname,\n          \\ '-o=' . go#util#OffsetCursor(),\n          \\ '-t']\n\n    if &modified\n      let l:stdin_content = join(go#util#GetLines(), \"\\n\")\n      call add(l:cmd, \"-i\")\n      let [l:out, l:err] = go#util#ExecInDir(l:cmd, l:stdin_content)\n    else\n      let [l:out, l:err] = go#util#ExecInDir(l:cmd)\n    endif\n  elseif bin_name == 'gopls'\n    if !go#config#GoplsEnabled()\n      call go#util#EchoError(\"go_def_mode is 'gopls', but gopls is disabled\")\n      return\n    endif\n\n    \" reset l:fname when using gopls so that the filename will be converted to\n    \" a URI correctly on windows.\n    let l:fname = expand('%')\n    let [l:line, l:col] = go#lsp#lsp#Position()\n    \" delegate to gopls, with an empty job object and an exit status of 0\n    \" (they're irrelevant for gopls).\n    if a:type\n      call go#lsp#TypeDef(l:fname, l:line, l:col, function('s:jump_to_declaration_cb', [a:mode, 'gopls', {}, 0]))\n    else\n      call go#lsp#Definition(l:fname, l:line, l:col, function('s:jump_to_declaration_cb', [a:mode, 'gopls', {}, 0]))\n    endif\n    return\n  else\n    call go#util#EchoError('go_def_mode value: '. bin_name .' is not valid. Valid values are: [godef, gopls]')\n    return\n  endif\n\n  if l:err\n    call go#util#EchoError(out)\n    return\n  endif\n\n  call go#def#jump_to_declaration(out, a:mode, bin_name)\nendfunction\n\nfunction! s:jump_to_declaration_cb(mode, bin_name, job, exit_status, data) abort dict\n  if a:exit_status != 0\n    return\n  endif\n\n  call go#def#jump_to_declaration(a:data[0], a:mode, a:bin_name)\n\n  \" capture the active window so that callbacks for jobs, exit_cb and\n  \" close_cb, and callbacks for gopls can return to it when a:mode caused a\n  \" split.\n  let self.winid = win_getid(winnr())\nendfunction\n\n\" go#def#jump_to_declaration parses out (expected to be\n\" 'filename:line:col: message').\nfunction! go#def#jump_to_declaration(out, mode, bin_name) abort\n  let final_out = a:out\n  if a:bin_name == \"godef\"\n    \" append the type information to the same line so it will be parsed\n    \" correctly using guru's output format.\n    \" This makes it compatible with guru output.\n    let final_out = join(split(a:out, '\\n'), ':')\n  endif\n\n  \" strip line ending\n  let out = split(final_out, go#util#LineEnding())[0]\n  if go#util#IsWin()\n    let parts = split(out, '\\(^[a-zA-Z]\\)\\@<!:')\n  else\n    let parts = split(out, ':')\n  endif\n\n  if len(parts) == 0\n    call go#util#EchoError('go jump_to_declaration '. a:bin_name .' output is not valid.')\n    return\n  endif\n\n  let line = 1\n  let col = 1\n  let ident = 0\n  let filename = parts[0]\n  if len(parts) > 1\n    let line = parts[1]\n  endif\n  if len(parts) > 2\n    let col = parts[2]\n  endif\n  if len(parts) > 3\n    let ident = parts[3]\n  endif\n\n  if exists('*settagstack') && has('patch-8.2.0077')\n    let l:tag = expand('<cword>')\n    let l:pos = [bufnr('')] + getcurpos()[1:]\n    let l:stack_entry = {'bufnr': l:pos[0], 'from': l:pos, 'tagname': l:tag}\n  else\n    let l:stack_entry = {'line': line(\".\"), 'col': col(\".\"), 'file': expand('%:p'), 'ident': ident}\n  endif\n\n  \" needed for restoring back user setting this is because there are two\n  \" modes of switchbuf which we need based on the split mode\n  let old_switchbuf = &switchbuf\n\n  normal! m'\n  if a:mode != '' || filename != fnamemodify(expand(\"%\"), ':p:gs?\\\\?/?')\n    \" jump to existing buffer if, 1. we have enabled it, 2. the buffer is loaded\n    \" and 3. there is buffer window number we switch to\n    if go#config#DefReuseBuffer() && bufwinnr(filename) != -1\n      \" jump to existing buffer if it exists\n      call win_gotoid(bufwinid(filename))\n    else\n      if &modified\n        let cmd = 'hide edit'\n      else\n        let cmd = 'edit'\n      endif\n\n      if a:mode == \"tab\"\n        let &switchbuf = \"useopen,usetab,newtab\"\n        if bufloaded(filename) == 0\n          tab split\n        else\n           let cmd = 'sbuf'\n        endif\n      elseif a:mode == \"split\"\n        split\n      elseif a:mode == \"vsplit\"\n        vsplit\n      endif\n\n      \" open the file and jump to line and column\n      try\n        exec cmd fnameescape(fnamemodify(filename, ':.'))\n      catch\n        if stridx(v:exception, ':E325:') < 0\n          call go#util#EchoError(v:exception)\n        endif\n      endtry\n    endif\n  endif\n  call cursor(line, col)\n  \" also align the line to middle of the view\n  normal! zz\n\n  if exists('*settagstack') && has('patch-8.2.0077')\n    \" Jump was successful, write previous location to tag stack.\n    let l:winid = win_getid()\n    let l:stack = gettagstack(l:winid)\n    let l:stack['items'] = [l:stack_entry]\n    call settagstack(l:winid, l:stack, 't')\n  else\n    \" Remove anything newer than the current position, just like basic\n    \" vim tag support\n    if s:go_stack_level == 0\n      let s:go_stack = []\n    else\n      let s:go_stack = s:go_stack[0:s:go_stack_level-1]\n    endif\n\n    \" increment the stack counter\n    let s:go_stack_level += 1\n\n    \" push it on to the jumpstack\n    call add(s:go_stack, l:stack_entry)\n  endif\n\n  let &switchbuf = old_switchbuf\nendfunction\n\nfunction! go#def#SelectStackEntry() abort\n  let target_window = go#ui#GetReturnWindow()\n  if empty(target_window)\n    let target_window = winnr()\n  endif\n\n  let highlighted_stack_entry = matchstr(getline(\".\"), '^..\\zs\\(\\d\\+\\)')\n  if !empty(highlighted_stack_entry)\n    execute target_window . \"wincmd w\"\n    call go#def#Stack(str2nr(highlighted_stack_entry))\n  endif\n\n  call go#ui#CloseWindow()\nendfunction\n\nfunction! go#def#StackUI() abort\n  if len(s:go_stack) == 0\n    call go#util#EchoError(\"godef stack empty\")\n    return\n  endif\n\n  let stackOut = ['\" <Up>,<Down>:navigate <Enter>:jump <Esc>,q:exit']\n\n  let i = 0\n  while i < len(s:go_stack)\n    let entry = s:go_stack[i]\n    let prefix = \"\"\n\n    if i == s:go_stack_level\n      let prefix = \">\"\n    else\n      let prefix = \" \"\n    endif\n\n    call add(stackOut, printf(\"%s %d %s|%d col %d|%s\",\n          \\ prefix, i+1, entry[\"file\"], entry[\"line\"], entry[\"col\"], entry[\"ident\"]))\n    let i += 1\n  endwhile\n\n  if s:go_stack_level == i\n    call add(stackOut, \"> \")\n  endif\n\n  call go#ui#OpenWindow(\"GoDef Stack\", stackOut, \"godefstack\")\n\n  noremap <buffer> <silent> <CR>  :<C-U>call go#def#SelectStackEntry()<CR>\n  noremap <buffer> <silent> <Esc> :<C-U>call go#ui#CloseWindow()<CR>\n  noremap <buffer> <silent> q     :<C-U>call go#ui#CloseWindow()<CR>\nendfunction\n\nfunction! go#def#StackClear(...) abort\n  let s:go_stack = []\n  let s:go_stack_level = 0\nendfunction\n\nfunction! go#def#StackPop(...) abort\n  if len(s:go_stack) == 0\n    call go#util#EchoError(\"godef stack empty\")\n    return\n  endif\n\n  if s:go_stack_level == 0\n    call go#util#EchoError(\"at bottom of the godef stack\")\n    return\n  endif\n\n  if !len(a:000)\n    let numPop = 1\n  else\n    let numPop = a:1\n  endif\n\n  let newLevel = str2nr(s:go_stack_level) - str2nr(numPop)\n  call go#def#Stack(newLevel + 1)\nendfunction\n\nfunction! go#def#Stack(...) abort\n  if len(s:go_stack) == 0\n    call go#util#EchoError(\"godef stack empty\")\n    return\n  endif\n\n  if !len(a:000)\n    \" Display interactive stack\n    call go#def#StackUI()\n    return\n  else\n    let jumpTarget = a:1\n  endif\n\n  if jumpTarget !~ '^\\d\\+$'\n    if jumpTarget !~ '^\\s*$'\n      call go#util#EchoError(\"location must be a number\")\n    endif\n    return\n  endif\n\n  let jumpTarget = str2nr(jumpTarget) - 1\n\n  if jumpTarget >= 0 && jumpTarget < len(s:go_stack)\n    let s:go_stack_level = jumpTarget\n    let target = s:go_stack[s:go_stack_level]\n\n    \" jump\n    if expand('%:p') != target[\"file\"]\n      if &modified\n        exec 'hide edit' target[\"file\"]\n      else\n        exec 'edit' target[\"file\"]\n      endif\n    endif\n    call cursor(target[\"line\"], target[\"col\"])\n    normal! zz\n  else\n    call go#util#EchoError(\"invalid location. Try :GoDefStack to see the list of valid entries\")\n  endif\nendfunction\n\nfunction s:def_job(args, state) abort\n  let l:start_options = go#job#Options(a:args)\n\n  let l:state = a:state\n  function! s:exit_cb(next, job, exitval) dict\n    call call(a:next, [a:job, a:exitval])\n    if has_key(self, 'winid')\n      call win_gotoid(self.winid)\n    endif\n  endfunction\n  let l:start_options.exit_cb = funcref('s:exit_cb', [l:start_options.exit_cb], l:state)\n\n  function! s:close_cb(next, ch) dict\n    call call(a:next, [a:ch])\n    if has_key(self, 'winid')\n      call win_gotoid(self.winid)\n    endif\n  endfunction\n  let l:start_options.close_cb = funcref('s:close_cb', [l:start_options.close_cb], l:state)\n\n  if &modified\n    let l:tmpname = tempname()\n    call writefile(split(a:args.input, \"\\n\"), l:tmpname, \"b\")\n    let l:start_options.in_io = \"file\"\n    let l:start_options.in_name = l:tmpname\n  endif\n\n  call go#job#Start(a:args.cmd, l:start_options)\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/def_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nscriptencoding utf-8\n\nfunc! Test_jump_to_declaration_godef() abort\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let l:filename = 'def/jump.go'\n    let l:lnum = 5\n    let l:col = 6\n    let l:tmp = gotest#load_fixture(l:filename)\n\n    let l:godef_out = printf(\"%s:%d:%d\\ndefined here as func main\", l:filename, l:lnum, l:col)\n    call go#def#jump_to_declaration(godef_out, \"\", 'godef')\n\n    call assert_equal(l:filename, bufname(\"%\"))\n    call assert_equal(l:lnum, getcurpos()[1])\n    call assert_equal(l:col, getcurpos()[2])\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_Jump_leaves_lists() abort\n  let l:wd = getcwd()\n  try\n    let l:filename = 'def/jump.go'\n    let l:tmp = gotest#load_fixture(l:filename)\n\n    let l:expected = [{'lnum': 10, 'bufnr': bufnr('%'), 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'quux'}]\n\n    call setloclist(0, copy(l:expected), 'r' )\n    call setqflist(copy(l:expected), 'r' )\n\n    let l:bufnr = bufnr('%')\n    call cursor(6, 7)\n   \n    if !go#util#has_job()\n      let g:go_def_mode='godef'\n    endif\n    call go#def#Jump('', 0)\n\n    if !go#util#has_job()\n    endif\n\n    let l:start = reltime()\n    while bufnr('%') == l:bufnr && reltimefloat(reltime(l:start)) < 10\n      sleep 100m\n    endwhile\n\n    let l:actual = getloclist(0)\n    call gotest#assert_quickfix(l:actual, l:expected)\n\n    let l:actual = getqflist()\n    call gotest#assert_quickfix(l:actual, l:expected)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_DefJump_gopls_simple_first() abort\n  if !go#util#has_job()\n    return\n  endif\n\n  let l:wd = getcwd()\n  try\n    let g:go_def_mode = 'gopls'\n\n    let l:tmp = gotest#write_file('simple/firstposition/firstposition.go', [\n          \\ 'package firstposition',\n          \\ '',\n          \\ 'func Example() {',\n          \\ \"\\tid := \" . '\"foo\"',\n          \\ \"\\tprintln(\" . '\"id:\", i\u001fd)',\n          \\ '}',\n          \\ ] )\n\n    let l:expected = [0, 4, 2, 0]\n\n    call assert_notequal(l:expected, getpos('.'))\n\n    call go#def#Jump('', 0)\n\n    let l:start = reltime()\n    while getpos('.') != l:expected && reltimefloat(reltime(l:start)) < 10\n      sleep 100m\n    endwhile\n\n    call assert_equal(l:expected, getpos('.'))\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_DefJump_gopls_simple_last() abort\n  if !go#util#has_job()\n    return\n  endif\n\n  let l:wd = getcwd()\n  try\n    let g:go_def_mode = 'gopls'\n\n    let l:tmp = gotest#write_file('simple/lastposition/lastposition.go', [\n          \\ 'package lastposition',\n          \\ '',\n          \\ 'func Example() {',\n          \\ \"\\tid := \" . '\"foo\"',\n          \\ \"\\tprintln(\" . '\"id:\", id\u001f)',\n          \\ '}',\n          \\ ] )\n\n    let l:expected = [0, 4, 2, 0]\n\n    call assert_notequal(l:expected, getpos('.'))\n\n    call go#def#Jump('', 0)\n\n    let l:start = reltime()\n    while getpos('.') != l:expected && reltimefloat(reltime(l:start)) < 10\n      sleep 100m\n    endwhile\n\n    call assert_equal(l:expected, getpos('.'))\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_DefJump_gopls_MultipleCodeUnit_first() abort\n  if !go#util#has_job()\n    return\n  endif\n\n  let l:wd = getcwd()\n  try\n    let g:go_def_mode = 'gopls'\n\n    let l:tmp = gotest#write_file('multiplecodeunit/firstposition/firstposition.go', [\n          \\ 'package firstposition',\n          \\ '',\n          \\ 'func Example() {',\n          \\ \"\\t𐐀, id := \" . '\"foo\", \"bar\"',\n          \\ \"\\tprintln(\" . '\"(𐐀, id):\", 𐐀, i\u001fd)',\n          \\ '}',\n          \\ ] )\n\n    let l:expected = [0, 4, 8, 0]\n    call assert_notequal(l:expected, getpos('.'))\n\n    call go#def#Jump('', 0)\n\n    let l:start = reltime()\n    while getpos('.') != l:expected && reltimefloat(reltime(l:start)) < 10\n      sleep 100m\n    endwhile\n\n    call assert_equal(l:expected, getpos('.'))\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\n\nfunc! Test_DefJump_gopls_MultipleCodeUnit_last() abort\n  if !go#util#has_job()\n    return\n  endif\n\n  let l:wd = getcwd()\n  try\n    let g:go_def_mode = 'gopls'\n\n    let l:tmp = gotest#write_file('multiplecodeunit/lastposition/lastposition.go', [\n          \\ 'package lastposition',\n          \\ '',\n          \\ 'func Example() {',\n          \\ \"\\t𐐀, id := \" . '\"foo\", \"bar\"',\n          \\ \"\\tprintln(\" . '\"(𐐀, id):\", 𐐀, id\u001f)',\n          \\ '}',\n          \\ ] )\n\n    let l:expected = [0, 4, 8, 0]\n    call assert_notequal(l:expected, getpos('.'))\n\n    call go#def#Jump('', 0)\n\n    let l:start = reltime()\n    while getpos('.') != l:expected && reltimefloat(reltime(l:start)) < 10\n      sleep 100m\n    endwhile\n\n    call assert_equal(l:expected, getpos('.'))\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/doc.vim",
    "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\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nscriptencoding utf-8\n\nlet s:buf_nr = -1\n\nfunction! go#doc#OpenBrowser(...) abort\n  let l:url = call('s:docURL', a:000)\n  if l:url is ''\n    call go#util#EchoWarning(\"could not find path for doc URL\")\n    return\n  endif\n  call go#util#OpenBrowser(l:url)\nendfunction\n\nfunction! s:docURL(...) abort\n  if len(a:000) == 0 && go#config#GoplsEnabled()\n    \" call go#lsp#DocLink directly instead of s:docURLFor, because s:docURLFor\n    \" will strip any version information from the URL.\n    let [l:out, l:err] = go#lsp#DocLink()\n    if !(l:err || len(l:out) is 0)\n      let l:url = printf('%s/%s', go#config#DocUrl(), l:out)\n    else\n      let l:url = ''\n    endif\n  else\n    let l:url = call('s:docURLFor', a:000)\n  endif\n\n  return l:url\nendfunction\n\nfunction! s:docURLFor(...) abort\n  let l:identifier = call('s:godocIdentifier', a:000)\n  if empty(l:identifier)\n    return ''\n  endif\n\n  let l:pkg = l:identifier[0]\n  let l:exported_name = ''\n  if len(l:identifier) > 1\n    let l:exported_name = l:identifier[1]\n  endif\n\n  \" example url: https://godoc.org/github.com/fatih/set#Set\n  return printf('%s/%s#%s', go#config#DocUrl(), l:pkg, l:exported_name)\nendfunction\n\nfunction! go#doc#Open(newmode, mode, ...) abort\n  let l:words = a:000\n  let l:package = ''\n  if a:0 is 0\n    let l:words = s:godocIdentifier()\n    if len(l:words) is 0\n      call go#util#EchoWarning(\"could not find doc identifier\")\n      return\n    endif\n    let l:package = l:words[0]\n  endif\n\n  if a:0 is 0 && &filetype == 'go' && go#config#GoplsEnabled()\n    \" use gopls to get documentation for go files\n    let [l:out, l:err] = go#lsp#Doc()\n  else\n    \" copy l:words before filtering so that filter() works when l:words is a:000\n    let l:words = filter(copy(l:words), 'v:val != \"\"')\n    let l:wd = go#util#Chdir(get(b:, 'go_godoc_wd', getcwd()))\n    try\n      let [l:out, l:err] = go#util#Exec(['go', 'doc'] + l:words)\n    finally\n      call go#util#Chdir(l:wd)\n    endtry\n  endif\n\n  if l:err\n    call go#util#EchoError(out)\n    return\n  endif\n\n  call s:GodocView(a:newmode, a:mode, l:out, l:package)\nendfunction\n\nfunction! s:GodocView(newposition, position, content, package) abort\n  \" popup window\n  if go#config#DocPopupWindow()\n    if exists('*popup_atcursor') && exists('*popup_clear')\n      call popup_clear()\n\n      let borderchars = ['-', '|', '-', '|', '+', '+', '+', '+']\n      if &encoding == \"utf-8\"\n        let borderchars = [ \"═\", \"║\", \"═\", \"║\", \"╔\",\"╗\", \"╝\", \"╚\" ]\n      endif\n\n      call popup_atcursor(split(a:content, '\\n'), {\n            \\ 'padding': [1, 1, 1, 1],\n            \\ 'borderchars': borderchars,\n            \\ 'border': [1, 1, 1, 1],\n            \\ })\n    elseif has('nvim') && exists('*nvim_open_win')\n      let lines = split(a:content, '\\n')\n      let height = 0\n      let width = 0\n      for line in lines\n        let lw = strdisplaywidth(line)\n        if lw > width\n          let width = lw\n        endif\n        let height += 1\n      endfor\n      let width += 1 \" right margin\n      let max_height = go#config#DocMaxHeight()\n      if height > max_height\n        let height = max_height\n      endif\n\n      let buf = nvim_create_buf(v:false, v:true)\n      call nvim_buf_set_lines(buf, 0, -1, v:true, lines)\n      let opts = {\n            \\ 'relative': 'cursor',\n            \\ 'row': 1,\n            \\ 'col': 0,\n            \\ 'width': width,\n            \\ 'height': height,\n            \\ 'style': 'minimal',\n            \\ 'border': 'double',\n            \\ }\n      call nvim_open_win(buf, v:true, opts)\n      setlocal nomodified nomodifiable filetype=godoc\n      let b:go_package_name = a:package\n\n      \" close easily with CR, Esc and q\n      noremap <buffer> <silent> <CR> :<C-U>close<CR>\n      noremap <buffer> <silent> <Esc> :<C-U>close<CR>\n      noremap <buffer> <silent> q :<C-U>close<CR>\n    endif\n    return\n  endif\n\n  let l:wd = getcwd()\n  \" set the working directory to the directory of the current file when the\n  \" filetype is go so that getting doc in the doc window will work regardless\n  \" of what the the starting window's working directory is.\n  if &filetype == 'go' && expand('%:p') isnot ''\n    let l:wd = expand('%:p:h')\n  endif\n\n  \" reuse existing buffer window if it exists otherwise create a new one\n  let is_visible = bufexists(s:buf_nr) && bufwinnr(s:buf_nr) != -1\n  if !bufexists(s:buf_nr)\n    call execute(a:newposition)\n    sil file `=\"[Godoc]\"`\n    let s:buf_nr = bufnr('%')\n  elseif bufwinnr(s:buf_nr) == -1\n    call execute(a:position)\n    call execute(printf('%dbuffer', s:buf_nr))\n  elseif bufwinid(s:buf_nr) != bufwinid('%')\n    call win_gotoid(bufwinid(s:buf_nr))\n  endif\n\n  if &filetype == 'godoc'\n    let l:wd = get(b:, 'go_godoc_wd', l:wd)\n  endif\n\n  \" if window was not visible then resize it\n  if !is_visible\n    if a:position == \"split\"\n      \" cap window height to 20, but resize it for smaller contents\n      let max_height = go#config#DocMaxHeight()\n      let content_height = len(split(a:content, \"\\n\"))\n      if content_height > max_height\n        exe 'resize ' . max_height\n      else\n        exe 'resize ' . content_height\n      endif\n    else\n      \" set a sane maximum width for vertical splits. In this case the minimum\n      \" that fits the godoc for package http without extra linebreaks and line\n      \" numbers on\n      exe 'vertical resize 84'\n    endif\n  endif\n\n  setlocal filetype=godoc\n  let b:go_package_name = a:package\n  let b:go_godoc_wd = l:wd\n  setlocal bufhidden=delete\n  setlocal buftype=nofile\n  setlocal noswapfile\n  setlocal nobuflisted\n  setlocal nocursorline\n  setlocal nocursorcolumn\n  setlocal iskeyword+=:\n  setlocal iskeyword-=-\n  setlocal modifiable\n\n  %delete _\n  call append(0, split(a:content, \"\\n\"))\n  sil $delete _\n  setlocal nomodifiable\n  sil normal! gg\n\n  \" close easily with enter\n  noremap <buffer> <silent> <CR> :<C-U>close<CR>\n  noremap <buffer> <silent> <Esc> :<C-U>close<CR>\n  \" make sure any key that sends an escape as a prefix (e.g. the arrow keys)\n  \" don't cause the window to close.\n  nnoremap <buffer> <silent> <Esc>[ <Esc>[\nendfunction\n\n\" returns the package and exported name. exported name might be empty.\n\" ie: fmt and Println\n\" ie: github.com/fatih/set and New\nfunction s:godocIdentifier(...) abort\n  let l:words = call('s:godocWord', a:000)\n  if empty(l:words)\n    return []\n  endif\n\n  let pkg = words[0]\n  if len(words) == 1\n    let exported_name = ''\n    if &filetype is 'godoc'\n      if pkg =~ '^[A-Z]'\n        let exported_name = pkg\n        let pkg = b:go_package_name\n      endif\n    endif\n  else\n    let exported_name = words[1]\n  endif\n\n  return [pkg, exported_name]\nendfunction\n\nfunction! s:godocWord(...) abort\n  let l:words = a:000\n  if a:0 is 0\n    if &filetype isnot 'godoc' && go#config#GoplsEnabled()\n      let [l:out, l:err] = go#lsp#DocLink()\n      if !(l:err || len(l:out) is 0)\n        \" strip out any version string in the doc link path.\n        let l:out = substitute(l:out, '@v[^/]\\+', '', '')\n        let words = split(l:out, '#')\n      else\n        let l:words = s:godocCursorWord()\n      endif\n    else\n      let l:words = s:godocCursorWord()\n    endif\n  endif\n\n  return l:words\nendfunction\n\nfunction! s:godocCursorWord() abort\n  let l:oldiskeyword = &iskeyword\n  \" TODO(bc): include / in iskeyword when filetype is godoc?\n  setlocal iskeyword+=.\n  let l:word = expand('<cword>')\n  let &iskeyword = l:oldiskeyword\n  let l:word = substitute(l:word, '[^a-zA-Z0-9\\\\/._~-]', '', 'g')\n  return split(l:word, '\\.\\ze[^./]\\+$')\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/extract.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! go#extract#Extract(line1, line2) abort\n  if !go#config#GoplsEnabled()\n    call go#util#EchoError('GoExtract requires gopls, but gopls is disabled')\n    return\n  endif\n\n  call go#lsp#Extract(a:line1, a:line2)\n  return\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/extract_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunc! Test_Extract() abort\n  let l:wd = getcwd()\n  try\n    let l:tmp = gotest#write_file('a/a.go', [\n          \\ 'package a',\n          \\ '',\n          \\ 'func f(v int) {',\n          \\ '\tfor i := 0; i < v; i++ {',\n          \\ \"\t\tp\\x1f\" . 'rintln(\"outputting something\")',\n          \\ '\t\tprintln(\"i is \", i+1)',\n          \\ '\t}',\n          \\ '}'])\n\n    silent! execute \"normal vj$\\<Esc>\"\n\n    call go#extract#Extract(line(\"'<\"), line(\"'>\"))\n\n    let start = reltime()\n    while &modified == 0 && reltimefloat(reltime(start)) < 10\n      sleep 100m\n    endwhile\n\n    call gotest#assert_buffer(1, [\n          \\ 'func f(v int) {',\n          \\ '\tfor i := 0; i < v; i++ {',\n          \\ '\t\tnewFunction(i)',\n          \\ '\t}',\n          \\ '}',\n          \\ '',\n          \\ 'func newFunction(i int) {',\n          \\ '\tprintln(\"outputting something\")',\n          \\ '\tprintln(\"i is \", i+1)',\n          \\ '}'])\n\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/fillstruct.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! go#fillstruct#FillStruct() abort\n  let l:mode = go#config#FillStructMode()\n  if l:mode is 'gopls'\n    if !go#config#GoplsEnabled()\n      call go#util#EchoError(\"go_fillstruct_mode is 'gopls', but gopls is disabled\")\n      return\n    endif\n\n    call go#lsp#FillStruct()\n    return\n  endif\n\n  let l:cmd = ['fillstruct',\n      \\ '-file', bufname(''),\n      \\ '-offset', go#util#OffsetCursor(),\n      \\ '-line', line('.')]\n      \" Needs: https://github.com/davidrjenni/reftools/pull/14\n      \"\\ '-tags', go#config#BuildTags()]\n\n  let l:buildtags = go#config#BuildTags()\n  if l:buildtags isnot ''\n    let l:cmd += ['-tags', l:buildtags]\n  endif\n\n  \" Read from stdin if modified.\n  if &modified\n    call add(l:cmd, '-modified')\n    let [l:out, l:err] = go#util#Exec(l:cmd, go#util#archive())\n  else\n    let [l:out, l:err] = go#util#Exec(l:cmd)\n  endif\n\n  if l:err\n    call go#util#EchoError(l:out)\n    return\n  endif\n\n  try\n    let l:json = json_decode(l:out)\n  catch\n    call go#util#EchoError(l:out)\n    return\n  endtry\n\n  \" Output is array:\n  \"[\n  \"   {\"start\": 92, \"end\": 106, \"code\": \"mail.Address{\\n\\tName:    \\\"\\\",\\n\\tAddress: \\\"\\\",\\n}\"},\n  \"   {...second struct...}\n  \" ]\n\n  let l:pos = getpos('.')\n\n  try\n    for l:struct in l:json\n      let l:code = split(l:struct['code'], \"\\n\")\n\n      \" Add any code before/after the struct.\n      exe l:struct['start'] . 'go'\n      let l:code[0] = getline('.')[:col('.')-1] . l:code[0]\n      exe l:struct['end'] . 'go'\n      let l:code[len(l:code)-1] .= getline('.')[col('.'):]\n\n      \" Indent every line except the first one; makes it look nice.\n      let l:indent = repeat(\"\\t\", indent('.') / &tabstop)\n      for l:i in range(1, len(l:code)-1)\n        let l:code[l:i] = l:indent . l:code[l:i]\n      endfor\n\n      \" Out with the old ...\n      exe 'normal! ' . l:struct['start'] . 'gov' . l:struct['end'] . 'gox'\n      \" ... in with the new.\n      call setline('.', l:code[0])\n      call append('.', l:code[1:])\n    endfor\n  finally\n    call setpos('.', l:pos)\n  endtry\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/fillstruct_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunc! Test_fillstruct() abort\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let g:go_fillstruct_mode = 'fillstruct'\n    let l:tmp = gotest#write_file('a/a.go', [\n          \\ 'package a',\n          \\ 'import \"net/mail\"',\n          \\ \"var addr = mail.\\x1fAddress{}\"])\n\n    call go#fillstruct#FillStruct()\n    call gotest#assert_buffer(1, [\n          \\ 'var addr = mail.Address{',\n          \\ '\\tName:    \"\",',\n          \\ '\\tAddress: \"\",',\n          \\ '}'])\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_fillstruct_line() abort\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let g:go_fillstruct_mode = 'fillstruct'\n    let l:tmp = gotest#write_file('a/a.go', [\n          \\ 'package a',\n          \\ 'import \"net/mail\"',\n          \\ \"\\x1f\" . 'var addr = mail.Address{}'])\n\n    call go#fillstruct#FillStruct()\n    call gotest#assert_buffer(1, [\n          \\ 'var addr = mail.Address{',\n          \\ '\\tName:    \"\",',\n          \\ '\\tAddress: \"\",',\n          \\ '}'])\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_fillstruct_two_line() abort\n  let l:wd = getcwd()\n  try\n    let g:go_fillstruct_mode = 'fillstruct'\n    let g:go_gopls_enabled = 0\n    let l:tmp = gotest#write_file('a/a.go', [\n          \\ 'package a',\n          \\ 'import (',\n          \\ '\"fmt\"',\n          \\ '\"net/mail\"',\n          \\ ')',\n          \\ \"\\x1f\" . 'func x() { fmt.Println(mail.Address{}, mail.Address{}) }'])\n\n    call go#fillstruct#FillStruct()\n    call gotest#assert_buffer(1, [\n          \\ 'import (',\n          \\ '\"fmt\"',\n          \\ '\"net/mail\"',\n          \\ ')',\n          \\ 'func x() { fmt.Println(mail.Address{',\n          \\ '\\tName:    \"\",',\n          \\ '\\tAddress: \"\",',\n          \\ '}, mail.Address{',\n          \\ '\\tName:    \"\",',\n          \\ '\\tAddress: \"\",',\n          \\ '}) }'])\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_fillstruct_two_cursor() abort\n  let l:wd = getcwd()\n  try\n    let g:go_fillstruct_mode = 'fillstruct'\n    let g:go_gopls_enabled = 0\n    let l:tmp = gotest#write_file('a/a.go', [\n          \\ 'package a',\n          \\ 'import (',\n          \\ '\"fmt\"',\n          \\ '\"net/mail\"',\n          \\ ')',\n          \\ \"func x() { fmt.Println(mail.Address{}, mail.Ad\\x1fdress{}) }\"])\n\n    call go#fillstruct#FillStruct()\n    call gotest#assert_buffer(1, [\n          \\ 'import (',\n          \\ '\"fmt\"',\n          \\ '\"net/mail\"',\n          \\ ')',\n          \\ 'func x() { fmt.Println(mail.Address{}, mail.Address{',\n          \\ '\\tName:    \"\",',\n          \\ '\\tAddress: \"\",',\n          \\ '}) }'])\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_gopls_fillstruct() abort\n  let l:wd = getcwd()\n  try\n    let g:go_fillstruct_mode = 'gopls'\n    let l:tmp = gotest#write_file('a/a.go', [\n          \\ 'package a',\n          \\ 'import \"net/mail\"',\n          \\ \"var addr = mail.\\x1fAddress{}\"])\n\n    call go#fillstruct#FillStruct()\n\n    let start = reltime()\n    while &modified == 0 && reltimefloat(reltime(start)) < 10\n      sleep 100m\n    endwhile\n\n    call gotest#assert_buffer(1, [\n          \\ 'var addr = mail.Address{',\n          \\ '\\tName:    \"\",',\n          \\ '\\tAddress: \"\",',\n          \\ '}'])\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\n\"func! Test_gopls_fillstruct_line() abort\n\"  let l:wd = getcwd()\n\"  try\n\"    let g:go_fillstruct_mode = 'gopls'\n\"    let l:tmp = gotest#write_file('a/a.go', [\n\"          \\ 'package a',\n\"          \\ 'import \"net/mail\"',\n\"          \\ \"\\x1f\" . 'var addr = mail.Address{}'])\n\"\n\"    call go#fillstruct#FillStruct()\n\"\n\"    let start = reltime()\n\"    while &modified == 0 && reltimefloat(reltime(start)) < 10\n\"      sleep 100m\n\"    endwhile\n\"\n\"    call gotest#assert_buffer(1, [\n\"          \\ 'var addr = mail.Address{',\n\"          \\ '\\tName:    \"\",',\n\"          \\ '\\tAddress: \"\",',\n\"          \\ '}'])\n\"  finally\n\"    call go#util#Chdir(l:wd)\n\"    call delete(l:tmp, 'rf')\n\"  endtry\n\"endfunc\n\nfunc! Test_gopls_fillstruct_two_cursor_first() abort\n  let l:wd = getcwd()\n  try\n    let g:go_fillstruct_mode = 'gopls'\n    let l:tmp = gotest#write_file('a/a.go', [\n          \\ 'package a',\n          \\ 'import (',\n          \\ '\"fmt\"',\n          \\ '\"net/mail\"',\n          \\ ')',\n          \\ \"func x() { fmt.Println(mail.Addr\\x1fess{}, mail.Address{}) }\"])\n\n    call go#fillstruct#FillStruct()\n\n    let start = reltime()\n    while &modified == 0 && reltimefloat(reltime(start)) < 10\n      sleep 100m\n    endwhile\n\n    call gotest#assert_buffer(1, [\n          \\ 'import (',\n          \\ '\"fmt\"',\n          \\ '\"net/mail\"',\n          \\ ')',\n          \\ 'func x() { fmt.Println(mail.Address{',\n          \\ '\\tName:    \"\",',\n          \\ '\\tAddress: \"\",',\n          \\ '}, mail.Address{}) }'])\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_gopls_fillstruct_two_cursor_second() abort\n  let l:wd = getcwd()\n  try\n    let g:go_fillstruct_mode = 'gopls'\n    let l:tmp = gotest#write_file('a/a.go', [\n          \\ 'package a',\n          \\ 'import (',\n          \\ '\"fmt\"',\n          \\ '\"net/mail\"',\n          \\ ')',\n          \\ \"func x() { fmt.Println(mail.Address{}, mail.Ad\\x1fdress{}) }\"])\n\n    call go#fillstruct#FillStruct()\n\n    let start = reltime()\n    while &modified == 0 && reltimefloat(reltime(start)) < 10\n      sleep 100m\n    endwhile\n\n    call gotest#assert_buffer(1, [\n          \\ 'import (',\n          \\ '\"fmt\"',\n          \\ '\"net/mail\"',\n          \\ ')',\n          \\ 'func x() { fmt.Println(mail.Address{}, mail.Address{',\n          \\ '\\tName:    \"\",',\n          \\ '\\tAddress: \"\",',\n          \\ '}) }'])\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/fmt.vim",
    "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\" fmt.vim: Vim command to format Go files with gofmt (and gofmt compatible\n\" toorls, such as goimports).\n\n\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\n\"  we have those problems :\n\"  http://stackoverflow.com/questions/12741977/prevent-vim-from-updating-its-undo-tree\n\"  http://stackoverflow.com/questions/18532692/golang-formatter-and-vim-how-to-destroy-history-record?rq=1\n\"\n\"  The below function is an improved version that aims to fix all problems.\n\"  it doesn't undo changes and break undo history.  If you are here reading\n\"  this and have VimL experience, please look at the function for\n\"  improvements, patches are welcome :)\nfunction! go#fmt#Format(withGoimport) abort\n  let l:bin_name = go#config#FmtCommand()\n  if a:withGoimport == 1\n    let l:mode = go#config#ImportsMode()\n    if l:mode == 'gopls'\n      if !go#config#GoplsEnabled()\n        call go#util#EchoError(\"go_imports_mode is 'gopls', but gopls is disabled\")\n        return\n      endif\n      call go#lsp#Imports()\n      return\n    endif\n\n    let l:bin_name = 'goimports'\n  endif\n\n  if l:bin_name == 'gopls'\n    if !go#config#GoplsEnabled()\n      call go#util#EchoError(\"go_fmt_command is 'gopls', but gopls is disabled\")\n      return\n    endif\n    call go#lsp#Format()\n    return\n  endif\n\n  if go#config#FmtExperimental()\n    \" Using winsaveview to save/restore cursor state has the problem of\n    \" closing folds on save:\n    \"   https://github.com/fatih/vim-go/issues/502\n    \" One fix is to use mkview instead. Unfortunately, this sometimes causes\n    \" other bad side effects:\n    \"   https://github.com/fatih/vim-go/issues/728\n    \" and still closes all folds if foldlevel>0:\n    \"   https://github.com/fatih/vim-go/issues/732\n    let l:curw = {}\n    try\n      mkview!\n    catch\n      let l:curw = winsaveview()\n    endtry\n\n    \" save our undo file to be restored after we are done. This is needed to\n    \" prevent an additional undo jump due to BufWritePre auto command and also\n    \" restore 'redo' history because it's getting being destroyed every\n    \" BufWritePre\n    let tmpundofile = tempname()\n    exe 'wundo! ' . tmpundofile\n  else\n    \" Save cursor position and many other things.\n    let l:curw = winsaveview()\n  endif\n\n  \" Write current unsaved buffer to a temp file\n  let l:tmpname = tempname() . '.go'\n  call writefile(go#util#GetLines(), l:tmpname)\n  if go#util#IsWin()\n    let l:tmpname = tr(l:tmpname, '\\', '/')\n  endif\n\n  let current_col = col('.')\n  let [l:out, l:err] = go#fmt#run(l:bin_name, l:tmpname, expand('%'))\n  let line_offset = len(readfile(l:tmpname)) - line('$')\n  let l:orig_line = getline('.')\n\n  if l:err == 0\n    call go#fmt#update_file(l:tmpname, expand('%'))\n  elseif !go#config#FmtFailSilently()\n    let l:errors = s:replace_filename(expand('%'), out)\n    call go#fmt#ShowErrors(l:errors)\n  endif\n\n  \" We didn't use the temp file, so clean up\n  call delete(l:tmpname)\n\n  if go#config#FmtExperimental()\n    \" restore our undo history\n    silent! exe 'rundo ' . tmpundofile\n    call delete(tmpundofile)\n\n    \" Restore our cursor/windows positions, folds, etc.\n    if empty(l:curw)\n      silent! loadview\n    else\n      call winrestview(l:curw)\n    endif\n  else\n    \" Restore our cursor/windows positions.\n    call winrestview(l:curw)\n  endif\n\n  \" be smart and jump to the line the new statement was added/removed and\n  \" adjust the column within the line\n  let l:lineno = line('.') + line_offset\n  call cursor(l:lineno, current_col + (len(getline(l:lineno)) - len(l:orig_line)))\n\n  \" Syntax highlighting breaks less often.\n  syntax sync fromstart\nendfunction\n\n\" update_file updates the target file with the given formatted source\nfunction! go#fmt#update_file(source, target)\n  \" remove undo point caused via BufWritePre\n  try | silent undojoin | catch | endtry\n\n  let old_fileformat = &fileformat\n  if exists(\"*getfperm\")\n    \" save file permissions\n    let original_fperm = getfperm(a:target)\n  endif\n\n  call rename(a:source, a:target)\n\n  \" restore file permissions\n  if exists(\"*setfperm\") && original_fperm != ''\n    call setfperm(a:target , original_fperm)\n  endif\n\n  \" reload buffer to reflect latest changes\n  silent edit!\n\n  call go#lsp#DidChange(fnamemodify(a:target, ':p'))\n\n  let &fileformat = old_fileformat\n  let &syntax = &syntax\n\n  call go#fmt#CleanErrors()\nendfunction\n\n\" run runs the gofmt/goimport command for the given source file and returns\n\" the output of the executed command. Target is the real file to be formatted.\nfunction! go#fmt#run(bin_name, source, target)\n  let l:cmd = s:fmt_cmd(a:bin_name, a:source, a:target)\n  if empty(l:cmd)\n    return\n  endif\n  return go#util#Exec(l:cmd)\nendfunction\n\n\" fmt_cmd returns the command to run as a list.\nfunction! s:fmt_cmd(bin_name, source, target)\n  let l:cmd = [a:bin_name, '-w']\n\n  \" add the options for binary (if any). go_fmt_options was by default of type\n  \" string, however to allow customization it's now a dictionary of binary\n  \" name mapping to options.\n  let opts = go#config#FmtOptions()\n  if type(opts) == type({})\n    let opts = has_key(opts, a:bin_name) ? opts[a:bin_name] : \"\"\n  endif\n  call extend(cmd, split(opts, \" \"))\n  if a:bin_name is# 'goimports'\n    call extend(cmd, [\"-srcdir\", a:target])\n  endif\n\n  call add(cmd, a:source)\n  return cmd\nendfunction\n\n\" replace_filename replaces the filename on each line of content with\n\" a:filename.\nfunction! s:replace_filename(filename, content) abort\n  let l:errors = split(a:content, '\\n')\n\n  let l:errors = map(l:errors, printf('substitute(v:val, ''^.\\{-}:'', ''%s:'', '''')', a:filename))\n  return join(l:errors, \"\\n\")\nendfunction\n\nfunction! go#fmt#CleanErrors() abort\n  let l:listtype = go#list#Type(\"GoFmt\")\n\n  \" clean up previous list\n  if l:listtype == \"quickfix\"\n    let l:list_title = getqflist({'title': 1})\n  else\n    let l:list_title = getloclist(0, {'title': 1})\n  endif\n\n  if has_key(l:list_title, 'title') && (l:list_title['title'] == 'Format' || l:list_title['title'] == 'GoMetaLinterAutoSave')\n    call go#list#Clean(l:listtype)\n  endif\nendfunction\n\n\" show_errors opens a location list and shows the given errors. If errors is\n\" empty, it closes the the location list.\nfunction! go#fmt#ShowErrors(errors) abort\n  let l:errorformat = '%f:%l:%c:\\ %m'\n  let l:listtype = go#list#Type(\"GoFmt\")\n\n  call go#list#ParseFormat(l:listtype, l:errorformat, a:errors, 'Format', 0)\n  let l:errors = go#list#Get(l:listtype)\n\n  \" this closes the window if there are no errors or it opens\n  \" it if there are any.\n  call go#list#Window(l:listtype, len(l:errors))\nendfunction\n\nfunction! go#fmt#ToggleFmtAutoSave() abort\n  if go#config#FmtAutosave()\n    call go#config#SetFmtAutosave(0)\n    call go#util#EchoProgress(\"auto fmt disabled\")\n    return\n  end\n\n  call go#config#SetFmtAutosave(1)\n  call go#util#EchoProgress(\"auto fmt enabled\")\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/fmt_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunc! Test_run_fmt() abort\n  let g:go_gopls_enabled = 0\n  let actual_file = tempname()\n  call writefile(readfile(\"test-fixtures/fmt/hello.go\"), actual_file)\n\n  let expected = join(readfile(\"test-fixtures/fmt/hello_golden.go\"), \"\\n\")\n\n  \" run our code\n  call go#fmt#run(\"gofmt\", actual_file, \"test-fixtures/fmt/hello.go\")\n\n  \" this should now contain the formatted code\n  let actual = join(readfile(actual_file), \"\\n\")\n\n  call assert_equal(expected, actual)\nendfunc\n\nfunc! Test_update_file() abort\n  let g:go_gopls_enabled = 0\n  let expected = join(readfile(\"test-fixtures/fmt/hello_golden.go\"), \"\\n\")\n  let source_file = tempname()\n  call writefile(readfile(\"test-fixtures/fmt/hello_golden.go\"), source_file)\n\n  let target_file = tempname()\n  call writefile([\"\"], target_file)\n\n  \" update_file now\n  call go#fmt#update_file(source_file, target_file)\n\n  \" this should now contain the formatted code\n  let actual = join(readfile(target_file), \"\\n\")\n\n  call assert_equal(expected, actual)\nendfunc\n\nfunc! Test_goimports() abort\n  let g:go_gopls_enabled = 0\n  let $GOPATH = printf('%s/%s', fnamemodify(getcwd(), ':p'), 'test-fixtures/fmt')\n  let actual_file = tempname()\n  call writefile(readfile(\"test-fixtures/fmt/src/imports/goimports.go\"), actual_file)\n\n  let expected = join(readfile(\"test-fixtures/fmt/src/imports/goimports_golden.go\"), \"\\n\")\n\n  \" run our code\n  call go#fmt#run(\"goimports\", actual_file, \"test-fixtures/fmt/src/imports/goimports.go\")\n\n  \" this should now contain the formatted code\n  let actual = join(readfile(actual_file), \"\\n\")\n\n  call assert_equal(expected, actual)\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/highlight_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! Test_gomodVersion_highlight() abort\n  try\n    syntax on\n\n    let g:go_gopls_enabled = 0\n    let l:wd = getcwd()\n    let l:dir = gotest#write_file('gomodtest/go.mod', [\n          \\ 'module github.com/fatih/vim-go',\n          \\ '',\n          \\ '\\x1frequire (',\n          \\ '\\tversion/simple v1.0.0',\n          \\ '\\tversion/simple-pre-release v1.0.0-rc',\n          \\ '\\tversion/simple-pre-release v1.0.0+meta',\n          \\ '\\tversion/simple-pre-release v1.0.0-rc+meta',\n          \\ '\\tversion/pseudo/premajor v1.0.0-20060102150405-0123456789abcdef',\n          \\ '\\tversion/pseudo/prerelease v1.0.0-prerelease.0.20060102150405-0123456789abcdef',\n          \\ '\\tversion/pseudo/prepatch v1.0.1-0.20060102150405-0123456789abcdef',\n          \\ '\\tversion/simple/incompatible v2.0.0+incompatible',\n          \\ '\\tversion/pseudo/premajor/incompatible v2.0.0-20060102150405-0123456789abcdef+incompatible',\n          \\ '\\tversion/pseudo/prerelease/incompatible v2.0.0-prerelease.0.20060102150405-0123456789abcdef+incompatible',\n          \\ '\\tversion/pseudo/prepatch/incompatible v2.0.1-0.20060102150405-0123456789abcdef+incompatible',\n          \\ ')'])\n\n    let l:lineno = 4\n    let l:lineclose = line('$')\n    while l:lineno < l:lineclose\n      let l:line = getline(l:lineno)\n      let l:col = col([l:lineno, '$']) - 1\n      let l:idx = len(l:line) - 1\n      let l:from = stridx(l:line, ' ') + 1\n\n      while l:idx >= l:from\n        call cursor(l:lineno, l:col)\n        let l:synname = synIDattr(synID(l:lineno, l:col, 1), 'name')\n        let l:errlen = len(v:errors)\n\n        call assert_equal('gomodVersion', l:synname, 'version on line ' . l:lineno)\n\n        \" continue at the next line if there was an error at this column;\n        \" there's no need to test each column once an error is detected.\n        if l:errlen < len(v:errors)\n          break\n        endif\n\n        let l:col -= 1\n        let l:idx -= 1\n      endwhile\n      let l:lineno += 1\n    endwhile\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunc\n\nfunction! Test_gomodVersion_incompatible_highlight() abort\n  try\n    syntax on\n\n    let g:go_gopls_enabled = 0\n    let l:wd = getcwd()\n    let l:dir = gotest#write_file('gomodtest/go.mod', [\n          \\ 'module github.com/fatih/vim-go',\n          \\ '',\n          \\ '\\x1frequire (',\n          \\ '\\tversion/invalid/premajor/incompatible v1.0.0-20060102150405-0123456789abcdef+incompatible',\n          \\ '\\tversion/invalid/prerelease/incompatible v1.0.0-prerelease.0.20060102150405-0123456789abcdef+incompatible',\n          \\ '\\tversion/invalid/prepatch/incompatible v1.0.1-0.20060102150405-0123456789abcdef+incompatible',\n          \\ ')'])\n\n    let l:lineno = 4\n    let l:lineclose = line('$')\n    while l:lineno < l:lineclose\n      let l:line = getline(l:lineno)\n      let l:col = col([l:lineno, '$']) - 1\n      let l:idx = len(l:line) - 1\n      let l:from = stridx(l:line, '+')\n\n      while l:idx >= l:from\n        call cursor(l:lineno, l:col)\n        let l:synname = synIDattr(synID(l:lineno, l:col, 1), 'name')\n        let l:errlen = len(v:errors)\n\n        call assert_notequal('gomodVersion', l:synname, 'version on line ' . l:lineno)\n\n        \" continue at the next line if there was an error at this column;\n        \" there's no need to test each column once an error is detected.\n        if l:errlen < len(v:errors)\n          break\n        endif\n\n        let l:col -= 1\n        let l:idx -= 1\n      endwhile\n      let l:lineno += 1\n    endwhile\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunc\n\nfunction! Test_numeric_literal_highlight() abort\n  syntax on\n  let g:go_gopls_enabled = 0\n\n  let l:tests = {\n        \\ 'lone zero': {'group': 'goDecimalInt', 'value': '0'},\n        \\ 'float loan zero': {'group': 'goFloat', 'value': '0.'},\n        \\ 'integer': {'group': 'goDecimalInt', 'value': '1234567890'},\n        \\ 'integerGrouped': {'group': 'goDecimalInt', 'value': '1_234_567_890'},\n        \\ 'hexadecimal': {'group': 'goHexadecimalInt', 'value': '0x0123456789abcdef'},\n        \\ 'hexadecimalGrouped': {'group': 'goHexadecimalInt', 'value': '0x012_345_678_9abc_def'},\n        \\ 'heXadecimal': {'group': 'goHexadecimalInt', 'value': '0X0123456789abcdef'},\n        \\ 'hexadecimalFloatUp': {'group': 'goHexadecimalFloat', 'value': '0x0123456789abcdef.0123456789abcdefp2'},\n        \\ 'hexadecimalFloatDown': {'group': 'goHexadecimalFloat', 'value': '0x0123456789abcdef.0123456789abcdefp-2'},\n        \\ 'octal': {'group': 'goOctalInt', 'value': '01234567'},\n        \\ 'octalPrefix': {'group': 'goOctalInt', 'value': '0o1234567'},\n        \\ 'octalGrouped': {'group': 'goOctalInt', 'value': '0o1_234_567'},\n        \\ 'OctalPrefix': {'group': 'goOctalInt', 'value': '0O1234567'},\n        \\ 'binaryInt': {'group': 'goBinaryInt', 'value': '0b0101'},\n        \\ 'binaryIntGrouped': {'group': 'goBinaryInt', 'value': '0b_01_01'},\n        \\ 'BinaryInt': {'group': 'goBinaryInt', 'value': '0B0101'},\n        \\ 'floatFractionalOnly': {'group': 'goFloat', 'value': '.1'},\n        \\ 'hexadecimalFloatFractionalOnly': {'group': 'goHexadecimalFloat', 'value': '0x.1'},\n        \\ 'floatIntegerOnly': {'group': 'goFloat', 'value': '1e6'},\n        \\ }\n\n  for l:kv in items(copy(l:tests))\n    let l:value = deepcopy(l:kv[1])\n    let l:value.group = substitute(l:value.group, 'go', 'goImaginary', '')\n    let l:value.group = substitute(l:value.group, 'Int$', '', '')\n    let l:value.value = printf('%si', l:value.value)\n    let l:tests[printf('imaginary %s', l:kv[0])] = l:value\n  endfor\n\n  for l:kv in items(copy(l:tests))\n    let l:value = deepcopy(l:kv[1])\n    let l:value.value = printf('-%s', l:value.value)\n    let l:tests[printf('negative %s', l:kv[0])] = l:value\n  endfor\n\n  for l:kv in items(tests)\n    let l:actual = s:numericHighlightGroupInAssignment(l:kv[0], l:kv[1].value)\n    call assert_equal(l:kv[1].group, l:actual, l:kv[1].value)\n\n    let l:groupName = 'goString'\n    let l:actual = s:stringHighlightGroupInAssignment(l:kv[0], l:kv[1].value)\n    call assert_equal('goString', l:actual, printf('\"%s\"', l:kv[1].value))\n  endfor\nendfunction\n\nfunction! Test_zero_as_index_element() abort\n  syntax on\n  let g:go_gopls_enabled = 0\n\n  let l:actual = s:numericHighlightGroupInSliceElement('zero-element', '0')\n  call assert_equal('goDecimalInt', l:actual)\n  let l:actual = s:numericHighlightGroupInMultidimensionalSliceElement('zero-element', '0')\n  call assert_equal('goDecimalInt', l:actual, 'multi-dimensional')\nendfunction\n\nfunction! Test_zero_as_slice_index() abort\n  syntax on\n  let g:go_gopls_enabled = 0\n\n  let l:actual = s:numericHighlightGroupInSliceIndex('zero-index', '0')\n  call assert_equal('goDecimalInt', l:actual)\n  let l:actual = s:numericHighlightGroupInMultidimensionalSliceIndex('zero-index', '0', '0')\n\n  call assert_equal('goDecimalInt', l:actual, 'multi-dimensional')\nendfunction\n\nfunction! Test_zero_as_start_slicing_slice() abort\n  syntax on\n  let g:go_gopls_enabled = 0\n\n  let l:actual = s:numericHighlightGroupInSliceSlicing('slice-slicing', '0', '1')\n  call assert_equal('goDecimalInt', l:actual)\nendfunction\n\nfunction! s:numericHighlightGroupInAssignment(testname, value)\n  let l:wd = getcwd()\n  let l:dir = gotest#write_file(printf('numeric/%s.go', a:testname), [\n        \\ 'package numeric',\n        \\ '',\n        \\ printf(\"var v = %s\\x1f\", a:value),\n        \\ ])\n\n  try\n    let l:pos = getcurpos()\n    let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')\n    return l:actual\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunction\n\nfunction! s:stringHighlightGroupInAssignment(testname, value)\n  let l:wd = getcwd()\n  let l:dir = gotest#write_file(printf('numeric/%s.go', a:testname), [\n        \\ 'package numeric',\n        \\ '',\n        \\ printf(\"var v = \\\"%s\\x1f\\\"\", a:value),\n        \\ ])\n\n  try\n    let l:pos = getcurpos()\n    let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')\n    return l:actual\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunction\n\nfunction! s:numericHighlightGroupInSliceElement(testname, value)\n  let l:wd = getcwd()\n  let l:dir = gotest#write_file(printf('numeric/slice-element/%s.go', a:testname), [\n        \\ 'package numeric',\n        \\ '',\n        \\ printf(\"v := []int{%s\\x1f}\", a:value),\n        \\ ])\n\n  try\n    let l:pos = getcurpos()\n    let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')\n    return l:actual\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunction\n\nfunction! s:numericHighlightGroupInMultidimensionalSliceElement(testname, value)\n  let l:wd = getcwd()\n  let l:dir = gotest#write_file(printf('numeric/slice-multidimensional-element/%s.go', a:testname), [\n        \\ 'package numeric',\n        \\ '',\n        \\ printf(\"v := [][]int{{%s\\x1f},{%s}}\", a:value, a:value),\n        \\ ])\n\n  try\n    let l:pos = getcurpos()\n    let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')\n    return l:actual\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunction\n\nfunction! s:numericHighlightGroupInSliceIndex(testname, value)\n  let l:wd = getcwd()\n  let l:dir = gotest#write_file(printf('numeric/slice-index/%s.go', a:testname), [\n        \\ 'package numeric',\n        \\ '',\n        \\ 'var sl []int',\n        \\ printf(\"println(sl[%s\\x1f])\", a:value),\n        \\ ])\n\n  try\n    let l:pos = getcurpos()\n    let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')\n    return l:actual\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunction\n\nfunction! s:numericHighlightGroupInMultidimensionalSliceIndex(testname, first, second)\n  let l:wd = getcwd()\n  let l:dir = gotest#write_file(printf('numeric/slice-multidimensional-index/%s.go', a:testname), [\n        \\ 'package numeric',\n        \\ '',\n        \\ 'var sl [][]int',\n        \\ printf(\"println(sl[%s\\x1f][%s])\", a:first, a:second),\n        \\ ])\n\n  try\n    let l:pos = getcurpos()\n    let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')\n    return l:actual\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunction\n\nfunction! s:numericHighlightGroupInSliceSlicing(testname, from, to)\n  let l:wd = getcwd()\n  let l:dir = gotest#write_file(printf('numeric/slice-slicing/%s.go', a:testname), [\n        \\ 'package numeric',\n        \\ '',\n        \\ 'var sl = []int{1,2}',\n        \\ printf(\"println(sl[%s\\x1f:%s])\", a:from, a:to),\n        \\ ])\n  try\n    let l:pos = getcurpos()\n    let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')\n    return l:actual\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunction\n\nfunction! Test_diagnostic_after_fmt() abort\n  let g:go_fmt_command = 'gofmt'\n  let g:go_diagnostics_level = 2\n  try\n    call s:diagnostic_after_write( [\n          \\ 'package main',\n          \\ 'import \"fmt\"',\n          \\ '',\n          \\ 'func main() {',\n          \\ '',\n          \\ \"\\tfmt.Println(h\\x1fello)\",\n          \\ '}',\n          \\ ], [])\n  finally\n  endtry\nendfunction\n\nfunction! Test_diagnostic_after_fmt_change() abort\n  \" craft a file that will be changed when its written (gofmt will change it).\n  let g:go_fmt_command = 'gofmt'\n  let g:go_diagnostics_level = 2\n  try\n    call s:diagnostic_after_write( [\n          \\ 'package main',\n          \\ 'import \"fmt\"',\n          \\ '',\n          \\ 'func main() {',\n          \\ '',\n          \\ \"fmt.Println(h\\x1fello)\",\n          \\ '}',\n          \\ ], [])\n  finally\n  endtry\nendfunction\n\nfunction! Test_diagnostic_after_fmt_cleared() abort\n  \" craft a file that will be fixed when it is written.\n  let g:go_fmt_command = 'gofmt'\n  let g:go_diagnostics_level = 2\n  try\n    call s:diagnostic_after_write( [\n          \\ 'package main',\n          \\ 'import \"fmt\"',\n          \\ '',\n          \\ 'func main() {',\n          \\ '',\n          \\ \"fmt.Println(h\\x1fello)\",\n          \\ '}',\n          \\ ], ['hello := \"hello, vim-go\"'])\n  finally\n  endtry\nendfunction\n\nfunction! Test_diagnostic_after_reload() abort\n  let g:go_diagnostics_level = 2\n  let l:wd = getcwd()\n  let l:dir = gotest#write_file('diagnostic/after-reload.go', [\n              \\ 'package main',\n              \\ 'import \"fmt\"',\n              \\ '',\n              \\ 'func main() {',\n              \\ '',\n              \\ \"\\tfmt.Println(h\\x1fello)\",\n              \\ '}',\n              \\ ])\n  try\n    call s:check_diagnostics('', 'goDiagnosticError', 'initial')\n    let l:pos = getcurpos()\n    edit\n    call setpos('.', l:pos)\n    call s:check_diagnostics('', 'goDiagnosticError', 'after-reload')\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunction\n\nfunction! s:diagnostic_after_write(contents, changes) abort\n  syntax on\n\n  let g:go_diagnostics_level = 2\n  let l:wd = getcwd()\n  let l:dir = gotest#write_file('diagnostic/after-write.go', a:contents)\n\n  try\n    let l:pos = getcurpos()\n    call s:check_diagnostics('', 'goDiagnosticError', 'initial')\n\n    \" write a:changes to the previous line and make sure l:actual and\n    \" l:expected are set so that they won't accidentally match on the next\n    \" check.\n    if len(a:changes) > 0\n      call append(l:pos[1]-1, a:changes)\n      let l:actual = 'goDiagnosticError'\n      let l:expected = ''\n    else\n      let l:actual = ''\n      let l:expected = 'goDiagnosticError'\n    endif\n\n    write\n\n    call s:check_diagnostics(l:actual, l:expected, 'after-write')\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunction\n\nfunction! s:check_diagnostics(actual, expected, when)\n  let l:actual = a:actual\n  let l:start = reltime()\n\n  while l:actual != a:expected && reltimefloat(reltime(l:start)) < 10\n    \" Get the cursor position on each iteration, because the cursor postion\n    \" may change between iterations when go#fmt#GoFmt formats, reloads the\n    \" file, and moves the cursor to try to keep it where the user expects it\n    \" to be when gofmt modifies the files.\n    let l:pos = getcurpos()\n    if !has('textprop')\n      let l:matches = getmatches()\n      if len(l:matches) == 0\n        let l:actual = ''\n      endif\n\n      for l:m in l:matches\n        let l:matchline = l:m.pos1[0]\n        if len(l:m.pos1) < 2\n          continue\n        endif\n        let l:matchcol = get(l:m.pos1, 1, 1)\n        if l:pos[1] == l:matchline && l:pos[2] >= l:matchcol && l:pos[2] <= l:matchcol + l:m.pos1[2]\n        \" Ideally, we'd check that the cursor is within the match, but when a\n        \" tab is added on the current line, the cursor position within the\n        \" line will stay constant while the line itself is shifted over by a\n        \" column, so just check the line itself instead of checking a precise\n        \" cursor location.\n        \" if l:pos[1] == l:matchline\n          let l:actual = l:m.group\n          break\n        endif\n      endfor\n\n      sleep 100m\n      continue\n    endif\n\n    let l:actual = get(prop_list(l:pos[1]), 0, {'type': ''}).type\n    sleep 100m\n  endwhile\n\n  call assert_equal(a:expected, l:actual, a:when)\nendfunction\n\nfunction! Test_goStringHighlight() abort\n  syntax on\n  let g:go_gopls_enabled = 0\n\n  let l:wd = getcwd()\n  let l:dir = gotest#write_file('highlight/gostring.go', [\n        \\ 'package highlight',\n        \\ '',\n        \\ 'import (',\n        \\ printf(\"\\t%s\", '\"fmt\"'),\n        \\ ')',\n        \\ '',\n        \\ printf('var s = \"%s\"', \"gostring\\x1f\"),\n        \\ ])\n\n  try\n    let l:pos = getcurpos()\n    let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')\n    call assert_equal('goString', l:actual)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunc\n\nfunction! Test_goImportStringHighlight() abort\n  syntax on\n  let g:go_gopls_enabled = 0\n\n  let l:wd = getcwd()\n  let l:dir = gotest#write_file('highlight/import.go', [\n        \\ 'package highlight',\n        \\ '',\n        \\ 'import (',\n        \\ printf('%s\"%s\"', \"\\t\", \"f\\x1fmt\"),\n        \\ ')',\n        \\ '',\n        \\ 'var s = fmt.Sprint(\"gostring\")',\n        \\ ])\n\n  try\n    let l:pos = getcurpos()\n    let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')\n    call assert_equal('goImportString', l:actual)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunc\n\nfunction! Test_goReceiverHighlight() abort\n  syntax on\n  let g:go_gopls_enabled = 0\n\n  let l:tests = {\n      \\ 'PointerReceiverVar': {'group': 'goReceiverVar', 'value': \"t\\x1f *T\"},\n      \\ 'ValueReceiverVar': {'group': 'goReceiverVar', 'value': \"t\\x1f T\"},\n      \\ 'PointerReceiverType': {'group': 'goReceiverType', 'value': \"t *T\\x1f\"},\n      \\ 'ValueReceiverType': {'group': 'goReceiverType', 'value': \"t T\\x1f\"},\n      \\ 'PointerReceiverTypeOmittedVar': {'group': 'goReceiverType', 'value': \"*T\\x1f\"},\n      \\ 'ValueReceiverTypeOmittedVar': {'group': 'goReceiverType', 'value': \"T\\x1f\"},\n      \\ 'GenericPointerReceiverVar': {'group': 'goReceiverVar', 'value': \"g\\x1f *G[int]\"},\n      \\ 'GenericValueReceiverVar': {'group': 'goReceiverVar', 'value': \"g\\x1f G[int]\"},\n      \\ 'GenericPointerReceiverType': {'group': 'goReceiverType', 'value': \"g *G\\x1f[int]\"},\n      \\ 'GenericValueReceiverType': {'group': 'goReceiverType', 'value': \"g G\\x1f[int]\"},\n      \\ 'GenericPointerReceiverTypeOmittedVar': {'group': 'goReceiverType', 'value': \"*G\\x1f[int]\"},\n      \\ 'GenericValueReceiverTypeOmittedVar': {'group': 'goReceiverType', 'value': \"G\\x1f[int]\"},\n      \\ }\n\n  let g:go_highlight_function_parameters = 1\n  for l:kv in items(l:tests)\n    let l:actual = s:receiverHighlightGroup(l:kv[0], l:kv[1].value)\n    call assert_equal(l:kv[1].group, l:actual, l:kv[0])\n  endfor\nendfunc\n\nfunction! s:receiverHighlightGroup(testname, value)\n  let l:package = tolower(a:testname)\n  let l:wd = getcwd()\n  let l:dir = gotest#write_file(printf('%s/%s.go', l:package, a:testname), [\n        \\ printf('package %s', l:package),\n        \\ '',\n        \\ 'type T struct{}',\n        \\ 'type G[T any] struct{}',\n        \\ printf('func (%s) Foo() {}', a:value),\n        \\ ])\n\n  try\n    let l:pos = getcurpos()\n    let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')\n    return l:actual\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunc\n\nfunction! Test_GoTypeHighlight() abort\n  syntax on\n  let g:go_gopls_enabled = 0\n\n  let l:tests = {\n      \\ 'StandardType': {'group': 'goTypeName', 'value': \"T\\x1f\"},\n      \\ 'GenericType': {'group': 'goTypeName', 'value': \"G\\x1f[T any]\"},\n      \\ }\n\n  let g:go_highlight_types = 1\n  for l:kv in items(l:tests)\n    let l:actual = s:typeHighlightGroup(l:kv[0], l:kv[1].value)\n    call assert_equal(l:kv[1].group, l:actual, l:kv[0])\n  endfor\nendfunc\n\nfunction! s:typeHighlightGroup(testname, value)\n  let l:package = tolower(a:testname)\n  let l:wd = getcwd()\n  let l:dir = gotest#write_file(printf('%s/%s.go', l:package, a:testname), [\n        \\ printf('package %s', l:package),\n        \\ '',\n        \\ printf('type %s struct{}', a:value),\n        \\ ])\n\n  try\n    let l:pos = getcurpos()\n    let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')\n    return l:actual\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunc\n\nfunction! Test_goFunction() abort\n  syntax on\n  let g:go_gopls_enabled = 0\n\n  let l:tests = {\n        \\ 'StandardFunction': {'group': 'goFunction', 'value': \"F\\x1f(){}\"},\n        \\ 'GenericFunction': {'group': 'goFunction', 'value': \"G\\x1f[T any](_ T){}\"},\n      \\ }\n\n  let g:go_highlight_functions = 1\n  for l:kv in items(l:tests)\n    let l:actual = s:functionHighlightGroup(l:kv[0], l:kv[1].value)\n    call assert_equal(l:kv[1].group, l:actual, l:kv[0])\n  endfor\nendfunc\n\nfunction! s:functionHighlightGroup(testname, value)\n  let l:package = tolower(a:testname)\n  let l:wd = getcwd()\n  let l:dir = gotest#write_file(printf('%s/%s.go', l:package, a:testname), [\n        \\ printf('package %s', l:package),\n        \\ '',\n        \\ printf('func %s', a:value),\n        \\ ])\n\n  try\n    let l:pos = getcurpos()\n    let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')\n    return l:actual\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunc\n\nfunction! Test_goFunctionCall() abort\n  syntax on\n  let g:go_gopls_enabled = 0\n\n  let l:tests = {\n      \\ 'StandardFunctionCall': {'group': 'goFunctionCall', 'value': \"f\\x1f()\"},\n      \\ 'GenericFunctionCall': {'group': 'goFunctionCall', 'value': \"g\\x1f[int](i)\"},\n      \\ }\n\n  let g:go_highlight_function_calls = 1\n  for l:kv in items(l:tests)\n    let l:actual = s:functionCallHighlightGroup(l:kv[0], l:kv[1].value)\n    call assert_equal(l:kv[1].group, l:actual, l:kv[0])\n  endfor\nendfunc\n\nfunction! s:functionCallHighlightGroup(testname, value)\n  let l:package = tolower(a:testname)\n  let l:wd = getcwd()\n  let l:dir = gotest#write_file(printf('%s/%s.go', l:package, a:testname), [\n        \\ printf('package %s', l:package),\n        \\ '',\n        \\ 'func f() {}',\n        \\ 'func g[T any](i T) {}',\n        \\ 'func init() {',\n        \\ printf(\"\\t%s\", a:value),\n        \\ '}',\n        \\ ])\n\n  try\n    let l:pos = getcurpos()\n    let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')\n    return l:actual\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunc\n\nfunction! Test_gomodToolchainVersion_highlight() abort\n  try\n    syntax on\n\n    let g:go_gopls_enabled = 0\n    let l:wd = getcwd()\n    let l:dir = gotest#write_file('gomodtest/go.mod', [\n          \\ 'module github.com/fatih/vim-go',\n          \\ '',\n          \\ 'toolchain default',\n          \\ 'toolchain go1',\n          \\ 'toolchain go1',\n          \\ 'toolchain go1.21',\n          \\ 'toolchain go1.21rc3',\n          \\ 'toolchain go1.21.3-somesuffix',\n          \\ 'toolchain go1.21rc2-somesuffix',\n          \\ 'toolchain go1.21 some-suffix',\n          \\ ''])\n\n    let l:lineno = 3\n    let l:lineclose = line('$')\n    while l:lineno < l:lineclose\n      let l:line = getline(l:lineno)\n      let l:split_idx = stridx(l:line, ' ')\n      let l:idx = 0\n      let l:col = 1\n\n      while l:idx < len(l:line) - 1\n        call cursor(l:lineno, l:col)\n        let l:synname = synIDattr(synID(l:lineno, l:col, 1), 'name')\n        let l:errlen = len(v:errors)\n\n        if l:idx < l:split_idx\n          call assert_equal('gomodToolchain', l:synname, 'toolchain on line ' . l:lineno . ' and col ' . l:col)\n        elseif l:idx > l:split_idx\n          call assert_equal('gomodToolchainVersion', l:synname, 'version on line ' . l:lineno . ' and col ' . l:col)\n        endif\n\n        if l:errlen < len(v:errors)\n          break\n        endif\n\n        let l:col += 1\n        let l:idx += 1\n      endwhile\n      let l:lineno += 1\n    endwhile\n\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunc\n\nfunction! Test_gomodToolchainVersion_invalid_highlight() abort\n  try\n    syntax on\n    let g:go_gopls_enabled = 0\n    let l:wd = getcwd()\n\n    \" 1. No release candidate for patch versions\n    \" 2+3. Release version can only be followed by 'rcN' or a valid suffix\n    \" 4+5. toolchain version must start with 'go'\n    let l:dir = gotest#write_file('gomodtest/go.mod', [\n          \\ 'module github.com/fatih/vim-go',\n          \\ '',\n          \\ 'toolchain go2',\n          \\ 'toolchain go1.21.1.4',\n          \\ 'toolchain go1.21.1blah',\n          \\ 'toolchain go1.21!some-suffix',\n          \\ 'toolchain something-else',\n          \\ ''])\n\n    let l:lineno = 3\n    let l:lineclose = line('$')\n    while l:lineno < l:lineclose\n      let l:line = getline(l:lineno)\n      let l:col = col([l:lineno, '$']) - 1\n      let l:idx = len(l:line) - 1\n      \" e.g. go1.21.1rc2 is valid until 'rc2'\n      \" each 'go*' test above has last version number '1'\n      let l:valid_version_start_idx = strridx(l:line, '1')\n\n      if l:valid_version_start_idx != -1\n        let l:end_idx = l:valid_version_start_idx\n      else\n        \" the whole version is invalid\n        let l:end_idx = stridx(l:line, ' ') + 1\n      endif\n\n      while l:idx > l:end_idx\n        call cursor(l:lineno, l:col)\n        let l:synname = synIDattr(synID(l:lineno, l:col, 1), 'name')\n        let l:errlen = len(v:errors)\n\n        call assert_notequal('gomodToolchainVersion', l:synname, 'version on line ' . l:lineno . ' and col ' . l:col)\n\n        if l:errlen < len(v:errors)\n          break\n        endif\n\n        let l:col -= 1\n        let l:idx -= 1\n      endwhile\n      let l:lineno += 1\n    endwhile\n\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunc\n\nfunction! Test_gomodGoVersion() abort\n  try\n    syntax on\n\n    let g:go_gopls_enabled = 0\n    let l:wd = getcwd()\n    let l:dir = gotest#write_file('gomodtest/go.mod', [\n          \\ 'module github.com/fatih/vim-go',\n          \\ '',\n          \\ 'go 1.20',\n          \\ 'go 1.21',\n          \\ 'go 1.21rc2',\n          \\ 'go 1.21.1',\n          \\ ''])\n\n    let l:lineno = 3\n    let l:lineclose = line('$')\n    while l:lineno < l:lineclose\n      let l:line = getline(l:lineno)\n      let l:split_idx = stridx(l:line, ' ')\n      let l:idx = len(l:line) - 1\n      let l:col = col([l:lineno, '$']) - 1\n\n      while l:idx > l:split_idx\n        call cursor(l:lineno, l:col)\n        let l:synname = synIDattr(synID(l:lineno, l:col, 1), 'name')\n        let l:errlen = len(v:errors)\n\n        call assert_equal('gomodGoVersion', l:synname, 'version on line ' . l:lineno . ' and col ' . l:col)\n        if l:errlen < len(v:errors)\n          break\n        endif\n\n        let l:col -= 1\n        let l:idx -= 1\n      endwhile\n      let l:lineno += 1\n    endwhile\n\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunc\n\n\nfunction! Test_goPackageComment_highlight() abort\n  try\n    syntax on\n\n    let g:go_gopls_enabled = 0\n    let l:wd = getcwd()\n    let l:dir = gotest#write_file('packageTest.go', [\n          \\ '// this is a package comment',\n          \\ 'package somepkg',\n          \\ '',\n          \\ '/*',\n          \\ 'this is also a package comment',\n          \\ '*/',\n          \\ 'package somepkg',\n          \\ '',\n          \\ 'var (',\n          \\ '\\t// this is a regular comment',\n          \\ '\\tpackages []string',\n          \\ ')',\n          \\ ''])\n\n    let l:package_comment_lines =  [1, 4, 5, 6]\n    for l:lineno in package_comment_lines\n      let l:line = getline(l:lineno)\n      let l:idx = 0\n      let l:end = len(l:line) - 1\n      let l:col = 1\n\n      while l:idx <= l:end\n        call cursor(l:lineno, l:col)\n        let l:synname = synIDattr(synID(l:lineno, l:col, 1), 'name')\n        let l:errlen = len(v:errors)\n\n        call assert_equal('goPackageComment', l:synname, 'version on line ' . l:lineno . ' and col ' . l:col)\n\n        if l:errlen < len(v:errors)\n          break\n        endif\n\n        let l:col += 1\n        let l:idx += 1\n      endwhile\n    endfor\n\n    let l:lineno = 10\n    let l:col = col([l:lineno, '$']) - 1\n    let l:end_idx = stridx(l:line, '\\t')\n    let l:idx = len(l:line - 1)\n\n    while l:idx > l:end_idx\n      call cursor(l:lineno, l:col)\n      let l:synname = synIDattr(synID(l:lineno, l:col, 1), 'name')\n      let l:errlen = len(v:errors)\n\n      call assert_equal('goComment', l:synname, 'version on line ' . l:lineno . ' and col ' . l:col)\n\n      if l:errlen < len(v:errors)\n        break\n      endif\n\n      let l:col -= 1\n      let l:idx -= 1\n    endwhile\n\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/iferr.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! go#iferr#Generate()\n  let [l:out, l:err] = go#util#Exec(['iferr',\n        \\ '-pos=' . go#util#OffsetCursor()], go#util#GetLines())\n  if len(l:out) == 1\n    return\n  endif\n  if getline('.') =~ '^\\s*$'\n    silent delete _\n    silent normal! k\n  endif\n  let l:pos = getcurpos()\n  call append(l:pos[1], split(l:out, \"\\n\"))\n  silent normal! j=2j\n  call setpos('.', l:pos)\n  silent normal! 4j\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/impl.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! go#impl#Impl(...) abort\n  let recv = \"\"\n  let iface = \"\"\n  let interactive = 0\n\n  let pos = getpos('.')\n\n  if a:0 is 0\n    \" Interactive mode if user didn't pass any arguments.\n    let recv = s:getReceiver()\n    let iface = input(\"vim-go: generating method stubs for interface: \")\n    redraw!\n    if empty(iface)\n      call go#util#EchoError('usage: interface type is not provided')\n      return\n    endif\n  elseif a:0 is 1\n    \" we assume the user only passed the interface type,\n    \" i.e: ':GoImpl io.Writer'\n    let recv = s:getReceiver()\n    let iface = a:1\n  elseif a:0 > 2\n    \" user passed receiver and interface type both,\n    \" i.e: 'GoImpl f *Foo io.Writer'\n    let recv = join(a:000[:-2], ' ')\n    let iface = a:000[-1]\n  else\n    call go#util#EchoError('usage: GoImpl {receiver} {receiver type} {interface}')\n    return\n  endif\n\n  \" Make sure we put the generated code *after* the struct.\n  if getline(\".\") =~ \"struct \"\n    normal! $%\n  endif\n\n  try\n    let dirname = fnameescape(expand('%:p:h'))\n    let [result, err] = go#util#Exec(['impl', '-dir', dirname, recv, iface])\n    let result = substitute(result, \"\\n*$\", \"\", \"\")\n    if err\n      call go#util#EchoError(result)\n      return\n    endif\n\n    if result is# ''\n      return\n    end\n\n    put =''\n    silent put =result\n  finally\n    call setpos('.', pos)\n  endtry\nendfunction\n\nfunction! s:getReceiver()\n  let receiveType = expand(\"<cword>\")\n  if receiveType == \"type\"\n    normal! w\n    let receiveType = expand(\"<cword>\")\n  elseif receiveType == \"struct\"\n    normal! ge\n    let receiveType = expand(\"<cword>\")\n  endif\n  return printf(\"%s *%s\", tolower(receiveType)[0], receiveType)\nendfunction\n\nif exists('*uniq')\n  function! s:uniq(list)\n    return uniq(a:list)\n  endfunction\nelse\n  \" Note: Believe that the list is sorted\n  function! s:uniq(list)\n    let i = len(a:list) - 1\n    while 0 < i\n      if a:list[i-1] ==# a:list[i]\n        call remove(a:list, i)\n        let i -= 2\n      else\n        let i -= 1\n      endif\n    endwhile\n    return a:list\n  endfunction\nendif\n\nfunction! s:root_dirs() abort\n  let dirs = []\n  let root = go#util#env(\"goroot\")\n  if root !=# '' && isdirectory(root)\n    call add(dirs, root)\n  endif\n\n  let paths = map(split(go#util#env(\"gopath\"), go#util#PathListSep()), \"substitute(v:val, '\\\\\\\\', '/', 'g')\")\n  if !empty(filter(paths, 'isdirectory(v:val)'))\n    call extend(dirs, paths)\n  endif\n\n  return dirs\nendfunction\n\nfunction! s:go_packages(dirs, arglead) abort\n  let pkgs = []\n  for dir in a:dirs\n      \" this may expand to multiple lines\n      let scr_root = expand(dir . '/src/')\n      for pkg in split(globpath(scr_root, a:arglead.'*'), \"\\n\")\n          if isdirectory(pkg)\n              let pkg .= '/'\n          elseif pkg !~ '\\.a$'\n              continue\n          endif\n\n          \" without this the result can have duplicates in form of\n          \" 'encoding/json' and '/encoding/json/'\n          let pkg = go#util#StripPathSep(pkg)\n\n          \" remove the scr root and keep the package in tact\n          let pkg = substitute(pkg, scr_root, \"\", \"\")\n          call add(pkgs, pkg)\n      endfor\n  endfor\n\n  return pkgs\nendfunction\n\nfunction! s:interface_list(pkg) abort\n  let [contents, err] = go#util#Exec(['go', 'doc', a:pkg])\n  if err\n    return []\n  endif\n\n  let contents = split(contents, \"\\n\")\n  call filter(contents, 'v:val =~# ''^type\\s\\+\\h\\w*\\s\\+interface''')\n  return map(contents, 'a:pkg . \".\" . matchstr(v:val, ''^type\\s\\+\\zs\\h\\w*\\ze\\s\\+interface'')')\nendfunction\n\n\" Complete package and interface for {interface}\nfunction! go#impl#Complete(arglead, cmdline, cursorpos) abort\n  let words = split(a:cmdline, '\\s\\+', 1)\n\n  if words[-1] ==# ''\n    \" if no words are given, just start completing the first package we found\n    return s:uniq(sort(s:go_packages(s:root_dirs(), a:arglead)))\n  elseif words[-1] =~# '^\\(\\h\\w.*\\.\\%(\\h\\w*\\)\\=$\\)\\@!\\S*$'\n    \" start matching go packages. It's negate match of the below match\n    return s:uniq(sort(s:go_packages(s:root_dirs(), a:arglead)))\n  elseif words[-1] =~# '^\\h\\w.*\\.\\%(\\h\\w*\\)\\=$'\n    \" match the following, anything that could indicate an interface candidate\n    \" \n    \"  io.\n    \"  io.Wr\n    \"  github.com/fatih/color.\n    \"  github.com/fatih/color.U\n    \"  github.com/fatih/color.Un\n    let splitted = split(words[-1], '\\.', 1)\n    let pkg = join(splitted[:-2], '.')\n    let interface = splitted[-1]\n    return s:uniq(sort(filter(s:interface_list(pkg), 'v:val =~? words[-1]')))\n  else\n    return []\n  endif\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/impl_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunc! Test_impl() abort\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let l:tmp = gotest#write_file('a/a.go', [\n          \\ 'package a',\n          \\ '',\n          \\ '\u001f'])\n\n    call go#impl#Impl('r', 'reader', 'io.Reader')\n    call gotest#assert_buffer(1, [\n          \\ 'func (r reader) Read(p []byte) (n int, err error) {',\n          \\ '\tpanic(\"not implemented\") // TODO: Implement',\n          \\ '}'])\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_impl_get() abort\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let l:tmp = gotest#write_file('a/a.go', [\n          \\ 'package a',\n          \\ '',\n          \\ 'type rea\u001fder struct {}'])\n\n    call go#impl#Impl('io.Reader')\n    call gotest#assert_buffer(0, [\n          \\ 'package a',\n          \\ '',\n          \\ 'type reader struct {}',\n          \\ '',\n          \\ 'func (r *reader) Read(p []byte) (n int, err error) {',\n          \\ '\tpanic(\"not implemented\") // TODO: Implement',\n          \\ '}'])\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/implements.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! go#implements#Implements(selected) abort\n  let l:mode = go#config#ImplementsMode()\n  if l:mode == 'gopls'\n    if !go#config#GoplsEnabled()\n      call go#util#EchoError(\"go_implements_mode is 'gopls', but gopls is disabled\")\n      return\n    endif\n    let [l:line, l:col] = getpos('.')[1:2]\n    let [l:line, l:col] = go#lsp#lsp#Position(l:line, l:col)\n    let l:fname = expand('%:p')\n    call go#lsp#Implements(l:fname, l:line, l:col, funcref('s:parse_output'))\n    return\n  else\n    call go#util#EchoWarning('unknown value for g:go_implements_mode')\n  endif\nendfunction\n\n\" This uses Vim's errorformat to parse the output and put it into a quickfix\n\" or locationlist.\nfunction! s:parse_output(exit_val, output) abort\n  if a:exit_val\n    call go#util#EchoError(a:output)\n    return\n  endif\n\n  let errformat = \",%f:%l:%c:\\ %m\"\n  let l:listtype = go#list#Type(\"GoImplements\")\n  call go#list#ParseFormat(l:listtype, errformat, a:output, 'implements', 0)\n\n  let errors = go#list#Get(l:listtype)\n  call go#list#Window(l:listtype, len(errors))\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/import.vim",
    "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\" Check out the docs for more information at /doc/vim-go.txt\n\"\n\n\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! go#import#SwitchImport(enabled, localname, path, bang) abort\n  let view = winsaveview()\n  let path = substitute(a:path, '^\\s*\\(.\\{-}\\)\\s*$', '\\1', '')\n\n  \" Quotes are not necessary, so remove them if provided.\n  if path[0] == '\"'\n    let path = strpart(path, 1)\n  endif\n  if path[len(path)-1] == '\"'\n    let path = strpart(path, 0, len(path) - 1)\n  endif\n\n  \" if given a trailing slash, eg. `github.com/user/pkg/`, remove it\n  if path[len(path)-1] == '/'\n    let path = strpart(path, 0, len(path) - 1)\n  endif\n\n  if path == ''\n    call s:Error('Import path not provided')\n    return\n  endif\n\n  if a:bang == \"!\"\n    let [l:out, l:err] = go#util#Exec(['go', 'get', '-u', '-v', path])\n    if err != 0\n      call s:Error(\"Can't find import: \" . path . \":\" . out)\n    endif\n  endif\n  let exists = go#tool#Exists(path)\n  if exists == -1\n    call s:Error(\"Can't find import: \" . path)\n    return\n  endif\n\n  \" Extract any site prefix (e.g. github.com/).\n  \" If other imports with the same prefix are grouped separately,\n  \" we will add this new import with them.\n  \" Only up to and including the first slash is used.\n  let siteprefix = matchstr(path, \"^[^/]*/\")\n\n  let qpath = '\"' . path . '\"'\n  if a:localname != ''\n    let qlocalpath = a:localname . ' ' . qpath\n  else\n    let qlocalpath = qpath\n  endif\n  let indentstr = 0\n  let packageline = -1 \" Position of package name statement\n  let appendline = -1  \" Position to introduce new import\n  let deleteline = -1  \" Position of line with existing import\n  let linesdelta = 0   \" Lines added/removed\n\n  \" Find proper place to add/remove import.\n  let line = 0\n  while line <= line('$')\n    let linestr = getline(line)\n\n    if linestr =~# '^package\\s'\n      let packageline = line\n      let appendline = line\n\n    elseif linestr =~# '^import\\s\\+(\\+)'\n      let appendline = line\n      let appendstr = qlocalpath\n    elseif linestr =~# '^import\\s\\+('\n      let appendstr = qlocalpath\n      let indentstr = 1\n      let appendline = line\n      let firstblank = -1\n      let lastprefix = \"\"\n      while line <= line(\"$\")\n        let line = line + 1\n        let linestr = getline(line)\n        let m = matchlist(getline(line), '^\\()\\|\\(\\s\\+\\)\\(\\w\\+\\s\\+\\)\\=\"\\(.\\+\\)\"\\)')\n        if empty(m)\n          if siteprefix == \"\" && a:enabled\n            \" must be in the first group\n            break\n          endif\n          \" record this position, but keep looking\n          if firstblank < 0\n            let firstblank = line\n          endif\n          continue\n        endif\n        if m[1] == ')'\n          \" if there's no match, add it to the first group\n          if appendline < 0 && firstblank >= 0\n            let appendline = firstblank\n          endif\n          break\n        endif\n        let lastprefix = matchstr(m[4], \"^[^/]*/\")\n        if a:localname != '' && m[3] != ''\n          let qlocalpath = printf('%-' . (len(m[3])-1) . 's %s', a:localname, qpath)\n        endif\n        let appendstr = m[2] . qlocalpath\n        let indentstr = 0\n        if m[4] == path\n          let appendline = -1\n          let deleteline = line\n          break\n        elseif m[4] < path\n          \" don't set candidate position if we have a site prefix,\n          \" we've passed a blank line, and this doesn't share the same\n          \" site prefix.\n          if siteprefix == \"\" || firstblank < 0 || match(m[4], \"^\" . siteprefix) >= 0\n            let appendline = line\n          endif\n        elseif siteprefix != \"\" && match(m[4], \"^\" . siteprefix) >= 0\n          \" first entry of site group\n          let appendline = line - 1\n          break\n        endif\n      endwhile\n      break\n\n    elseif linestr =~# '^import '\n      if appendline == packageline\n        let appendstr = 'import ' . qlocalpath\n        let appendline = line - 1\n      endif\n      let m = matchlist(linestr, '^import\\(\\s\\+\\)\\(\\S*\\s*\\)\"\\(.\\+\\)\"')\n      if !empty(m)\n        if m[3] == path\n          let appendline = -1\n          let deleteline = line\n          break\n        endif\n        if m[3] < path\n          let appendline = line\n        endif\n        if a:localname != '' && m[2] != ''\n          let qlocalpath = printf(\"%s %\" . len(m[2])-1 . \"s\", a:localname, qpath)\n        endif\n        let appendstr = 'import' . m[1] . qlocalpath\n      endif\n\n    elseif linestr =~# '^\\(var\\|const\\|type\\|func\\)\\>'\n      break\n\n    endif\n    let line = line + 1\n  endwhile\n\n  \" Append or remove the package import, as requested.\n  if a:enabled\n    if deleteline != -1\n      call s:Error(qpath . ' already being imported')\n    elseif appendline == -1\n      call s:Error('No package line found')\n    else\n      if appendline == packageline\n        call append(appendline + 0, '')\n        call append(appendline + 1, 'import (')\n        call append(appendline + 2, ')')\n        let appendline += 2\n        let linesdelta += 3\n        let appendstr = qlocalpath\n        let indentstr = 1\n        call append(appendline, appendstr)\n      elseif getline(appendline) =~# '^import\\s\\+(\\+)'\n        call setline(appendline, 'import (')\n        call append(appendline + 0, appendstr)\n        call append(appendline + 1, ')')\n        let linesdelta -= 1\n        let indentstr = 1\n      else\n        call append(appendline, appendstr)\n      endif\n      execute appendline + 1\n      if indentstr\n        execute 'normal! >>'\n      endif\n      let linesdelta += 1\n    endif\n  else\n    if deleteline == -1\n      call s:Error(qpath . ' not being imported')\n    else\n      execute deleteline . 'd'\n      let linesdelta -= 1\n\n      if getline(deleteline-1) =~# '^import\\s\\+(' && getline(deleteline) =~# '^)'\n        \" Delete empty import block\n        let deleteline -= 1\n        execute deleteline . \"d\"\n        execute deleteline . \"d\"\n        let linesdelta -= 2\n      endif\n\n      if getline(deleteline) == '' && getline(deleteline - 1) == ''\n        \" Delete spacing for removed line too.\n        execute deleteline . \"d\"\n        let linesdelta -= 1\n      endif\n    endif\n  endif\n\n  \" Adjust view for any changes.\n  let view.lnum += linesdelta\n  let view.topline += linesdelta\n  if view.topline < 0\n    let view.topline = 0\n  endif\n\n  \" Put buffer back where it was.\n  call winrestview(view)\n\nendfunction\n\n\nfunction! s:Error(s) abort\n  echohl Error | echo a:s | echohl None\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/import_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunc! Test_SwitchImportAddIgnoresCommented()\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let l:tmp = gotest#write_file('import/import.go', [\n          \\ 'package import',\n          \\ '',\n          \\ 'import (',\n          \\ \"\\t\" . '// \"fmt\"',\n          \\ \"\\t\" . '\"io\"',\n          \\ \"\\t\" . '\"ioutil\"',\n          \\ \"\\t\" . '\"os\"',\n          \\ ')',\n          \\ '',\n          \\ 'func main() {',\n          \\ ' io.Copy(ioutil.Discard, os.Stdin)',\n          \\ ' fmt.Println(\"import the package\")',\n          \\ '}',\n        \\ ])\n    call go#import#SwitchImport(1, '', 'fmt', 0)\n\n    let l:actual = getline(4)\n    call assert_equal(\"\\t\" . '\"fmt\"', l:actual)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/indent_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunc! Test_indent_raw_string() abort\n  \" The goRawString discovery requires that syntax be enabled.\n  syntax on\n  let g:go_gopls_enabled = 0\n\n  let l:wd = getcwd()\n  try\n    let l:dir= gotest#write_file('indent/indent.go', [\n          \\ 'package main',\n          \\ '',\n          \\ 'import \"fmt\"',\n          \\ '',\n          \\ 'func main() {',\n          \\\t\"\\t\\x1fconst msg = `\",\n          \\ '`',\n          \\ '\\tfmt.Println(msg)',\n          \\ '}'])\n\n    silent execute \"normal o\" . \"not indented\\<Esc>\"\n    let l:indent = indent(line('.'))\n    call assert_equal(0, l:indent)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\n\n  let l:wd = getcwd()\n  try\n    let l:dir= gotest#write_file('indent/indent.go', [\n          \\ 'package main',\n          \\ '',\n          \\ 'import \"fmt\"',\n          \\ '',\n          \\ 'func main() {',\n          \\\t\"\\t\\x1fmsg := `\",\n          \\ '`',\n          \\ '\\tfmt.Println(msg)',\n          \\ '}'])\n\n    silent execute \"normal o\" . \"not indented\\<Esc>\"\n    let l:indent = indent(line('.'))\n    call assert_equal(0, l:indent)\n  finally\n    call delete(l:dir, 'rf')\n    call go#util#Chdir(l:wd)\n  endtry\n\n  let l:wd = getcwd()\n  try\n    let l:dir= gotest#write_file('indent/indent.go', [\n          \\ 'package main',\n          \\ '',\n          \\ 'import \"fmt\"',\n          \\ '',\n          \\ 'func main() {',\n          \\\t\"\\tconst msg = `\",\n          \\ \"\\t\\x1findented\",\n          \\ '`',\n          \\ '\\tfmt.Println(msg)',\n          \\ '}'])\n\n    silent execute \"normal o\" . \"indented\\<Esc>\"\n    let l:indent = indent(line('.'))\n    call assert_equal(shiftwidth(), l:indent)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:dir, 'rf')\n  endtry\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/issue.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nlet s:templatepath = go#util#Join(resolve(expand('<sfile>:p:h:h:h')), '.github', 'issue_template.md')\n\nfunction! go#issue#New() abort\n  let body = go#uri#Encode(s:issuebody())\n  let url = \"https://github.com/fatih/vim-go/issues/new?template=default.md&body=\" . l:body\n  call go#util#OpenBrowser(l:url)\nendfunction\n\nfunction! s:issuebody() abort\n  let lines = readfile(s:templatepath)\n\n  let rtrimpat = '[[:space:]]\\+$'\n  let body = []\n  for l in lines\n    let body = add(body, l)\n\n    if l =~ '^<!-- :version'\n      let out = execute('version')\n      let body = extend(body, split(out, \"\\n\")[0:2])\n    elseif l =~ '^<!-- go version -->'\n      let [out, err] = go#util#Exec(['go', 'version'])\n      let body = add(body, substitute(l:out, rtrimpat, '', ''))\n    elseif l =~ '^<!-- go env -->'\n      let [out, err] = go#util#ExecInDir(['go', 'env'])\n      let body = add(body, substitute(l:out, rtrimpat, '', ''))\n    elseif l=~ '^<!-- gopls version -->'\n      let [out, err] = go#util#Exec(['gopls', 'version'])\n      let body = add(body, substitute(l:out, rtrimpat, '', ''))\n    endif\n  endfor\n\n  let body = add(body, \"\\n#### vim-go configuration:\\n<details><summary>vim-go configuration</summary><br><pre>\")\n\n  for k in keys(g:)\n    if k =~ '^go_'\n      let body = add(body, 'g:' . k . ' = ' . string(get(g:, k)))\n    endif\n  endfor\n\n  let body = add(body, '</pre></details>')\n\n  let body = add(body, printf(\"\\n#### filetype detection configuration:\\n<details><summary>filetype detection</summary><br><pre>%s\", execute('filetype')))\n  let body = add(body, '</pre></details>')\n\n  return join(body, \"\\n\")\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/job.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\n\" Spawn starts an asynchronous job. See the description of go#job#Options to\n\" understand the args parameter.\n\"\n\" Spawn returns a job.\nfunction! go#job#Spawn(cmd, args)\n  let l:options = go#job#Options(a:args)\n  return go#job#Start(a:cmd, l:options)\nendfunction\n\n\" Options returns callbacks to be used with job_start. It is abstracted to be\n\" used with various go commands, such as build, test, install, etc.. This\n\" allows us to avoid writing the same callback over and over for some\n\" commands. It's fully customizable so each command can change it to its own\n\" logic.\n\"\n\" args is a dictionary with the these keys:\n\"   'bang':\n\"     Set to 0 to jump to the first error in the error list.\n\"     Defaults to 0.\n\"   'statustype':\n\"     The status type to use when updating the status.\n\"     See statusline.vim.\n\"   'for':\n\"     The g:go_list_type_command key to use to get the error list type to use.\n\"     Errors will not be handled when the value is '_'.\n\"     Defaults to '_job'\n\"   'errorformat':\n\"     The errorformat string to use when parsing errors. Defaults to\n\"     &errorformat.\n\"     See :help 'errorformat'.\n\"   'complete':\n\"     A function to call after the job exits and the channel is closed. The\n\"     function will be passed three arguments: the job, its exit code, and the\n\"     list of messages received from the channel. The default is a no-op. A\n\"     custom value can modify the messages before they are processed by the\n\"     returned exit_cb and close_cb callbacks. When the function is called,\n\"     the current window will be the window that was hosting the buffer when\n\"     the job was started. After it returns, the current window will be\n\"     restored to what it was before the function was called.\n\"   'preserveerrors':\n\"     A function that will be passed one value, the list type. It should\n\"     return a boolean value that indicates whether any errors encountered\n\"     should be consider additive to the existing set of errors. This is\n\"     mostly useful for a set of commands that are run via autocmds.\n\"\n\" The return value is a dictionary with these keys:\n\"   'callback':\n\"     A function suitable to be passed as a job callback handler. See\n\"     job-callback.\n\"   'exit_cb':\n\"     A function suitable to be passed as a job exit_cb handler. See\n\"     job-exit_cb.\n\"   'close_cb':\n\"     A function suitable to be passed as a job close_cb handler. See\n\"     job-close_cb.\n\"   'cwd':\n\"     The path to the directory which contains the current buffer. The\n\"     callbacks are configured to expect this directory is the working\n\"     directory for the job; it should not be modified by callers.\nfunction! go#job#Options(args)\n  let cbs = {}\n  let state = {\n        \\ 'winid': win_getid(winnr()),\n        \\ 'dir': getcwd(),\n        \\ 'jobdir': expand(\"%:p:h\"),\n        \\ 'messages': [],\n        \\ 'bang': 0,\n        \\ 'for': \"_job\",\n        \\ 'exited': 0,\n        \\ 'exit_status': 0,\n        \\ 'closed': 0,\n        \\ 'errorformat': &errorformat,\n        \\ 'statustype' : '',\n      \\ }\n\n  let cbs.cwd = state.jobdir\n\n  if has_key(a:args, 'bang')\n    let state.bang = a:args.bang\n  endif\n\n  if has_key(a:args, 'for')\n    let state.for = a:args.for\n  endif\n\n  if has_key(a:args, 'statustype')\n    let state.statustype = a:args.statustype\n  endif\n\n  if has_key(a:args, 'errorformat')\n    let state.errorformat = a:args.errorformat\n  endif\n\n  if has_key(a:args, 'preserveerrors')\n    let state.preserveerrors = a:args.preserveerrors\n  endif\n\n  function state.complete(job, exit_status, data)\n    if has_key(self, 'custom_complete')\n      let l:winid = win_getid(winnr())\n      \" Always set the active window to the window that was active when the job\n      \" was started. Among other things, this makes sure that the correct\n      \" window's location list will be populated when the list type is\n      \" 'location' and the user has moved windows since starting the job.\n      call win_gotoid(self.winid)\n      call self.custom_complete(a:job, a:exit_status, a:data)\n      call win_gotoid(l:winid)\n    endif\n\n    call self.show_errors(a:job, a:exit_status, a:data)\n  endfunction\n\n  function state.show_status(job, exit_status) dict\n    if self.statustype == ''\n      return\n    endif\n\n    if go#config#EchoCommandInfo()\n      let prefix = '[' . self.statustype . '] '\n      if a:exit_status == 0\n        call go#util#EchoSuccess(prefix . \"SUCCESS\")\n      else\n        call go#util#EchoError(prefix . \"FAIL\")\n      endif\n    endif\n\n    let status = {\n          \\ 'desc': 'last status',\n          \\ 'type': self.statustype,\n          \\ 'state': \"success\",\n          \\ }\n\n    if a:exit_status\n      let status.state = \"failed\"\n    endif\n\n    if has_key(self, 'started_at')\n      let elapsed_time = reltimestr(reltime(self.started_at))\n      \" strip whitespace\n      let elapsed_time = substitute(elapsed_time, '^\\s*\\(.\\{-}\\)\\s*$', '\\1', '')\n      let status.state .= printf(\" (%ss)\", elapsed_time)\n    endif\n\n    call go#statusline#Update(self.jobdir, status)\n  endfunction\n\n  if has_key(a:args, 'complete')\n    let state.custom_complete = a:args.complete\n  endif\n\n  \" explicitly bind _start to state so that within it, self will\n  \" always refer to state. See :help Partial for more information.\n  \"\n  \" _start is intended only for internal use and should not be referenced\n  \" outside of this file.\n  let cbs._start = function('s:start', [''], state)\n\n  \" explicitly bind callback to state so that within it, self will\n  \" always refer to state. See :help Partial for more information.\n  let cbs.callback = function('s:callback', [], state)\n\n  \" explicitly bind exit_cb to state so that within it, self will always refer\n  \" to state. See :help Partial for more information.\n  let cbs.exit_cb = function('s:exit_cb', [], state)\n\n  \" explicitly bind close_cb to state so that within it, self will\n  \" always refer to state. See :help Partial for more information.\n  let cbs.close_cb = function('s:close_cb', [], state)\n\n  function state.show_errors(job, exit_status, data)\n    if self.for == '_'\n      return\n    endif\n\n    let l:winid = win_getid(winnr())\n    \" Always set the active window to the window that was active when the job\n    \" was started. Among other things, this makes sure that the correct\n    \" window's location list will be populated when the list type is\n    \" 'location' and the user has moved windows since starting the job.\n    call win_gotoid(self.winid)\n\n    let l:listtype = go#list#Type(self.for)\n\n    let l:preserveerrors = 0\n    if has_key(self, 'preserveerrors')\n      let l:preserveerrors = self.preserveerrors(l:listtype)\n    endif\n\n    if a:exit_status == 0\n      if !l:preserveerrors\n        call go#list#Clean(l:listtype)\n        call win_gotoid(l:winid)\n      endif\n      return\n    endif\n\n    let l:listtype = go#list#Type(self.for)\n    if len(a:data) == 0\n      if !l:preserveerrors\n        call go#list#Clean(l:listtype)\n        call win_gotoid(l:winid)\n      endif\n      return\n    endif\n\n    let out = join(self.messages, \"\\n\")\n\n    try\n      \" parse the errors relative to self.jobdir\n      call go#util#Chdir(self.jobdir)\n      call go#list#ParseFormat(l:listtype, self.errorformat, out, self.for, l:preserveerrors)\n      let errors = go#list#Get(l:listtype)\n    finally\n      call go#util#Chdir(self.dir)\n    endtry\n\n    if empty(errors)\n      \" failed to parse errors, output the original content\n      call go#util#EchoError([self.dir] + self.messages)\n      call win_gotoid(l:winid)\n      return\n    endif\n\n    \" only open the error window if user was still in the window from which\n    \" the job was started.\n    if self.winid == l:winid\n      call go#list#Window(l:listtype, len(errors))\n      if self.bang\n        call win_gotoid(l:winid)\n      else\n        call go#list#JumpToFirst(l:listtype)\n      endif\n    endif\n  endfunction\n\n  return cbs\nendfunction\n\nfunction! s:start(args) dict\n  if go#config#EchoCommandInfo() && self.statustype != \"\"\n    let prefix = '[' . self.statustype . '] '\n    call go#util#EchoSuccess(prefix . \"dispatched\")\n  endif\n\n  if self.statustype != ''\n    let status = {\n          \\ 'desc': 'current status',\n          \\ 'type': self.statustype,\n          \\ 'state': \"started\",\n          \\ }\n\n    call go#statusline#Update(self.jobdir, status)\n  endif\n  let self.started_at = reltime()\nendfunction\n\nfunction! s:callback(chan, msg) dict\n  call add(self.messages, a:msg)\nendfunction\n\nfunction! s:exit_cb(job, exitval) dict\n  let self.exit_status = a:exitval\n  let self.exited = 1\n\n  call self.show_status(a:job, a:exitval)\n\n  if self.closed || has('nvim')\n    call self.complete(a:job, self.exit_status, self.messages)\n  endif\nendfunction\n\nfunction! s:close_cb(ch) dict\n  let self.closed = 1\n\n  if self.exited\n    let job = ch_getjob(a:ch)\n    call self.complete(job, self.exit_status, self.messages)\n  endif\nendfunction\n\n\" go#job#Start runs a job. The options are expected to be the options\n\" suitable for Vim8 jobs. When called from Neovim, Vim8 options will be\n\" transformed to their Neovim equivalents.\nfunction! go#job#Start(cmd, options)\n  let l:options = copy(a:options)\n\n  if has('nvim')\n    let l:options = s:neooptions(l:options)\n  endif\n\n  \" Verify that the working directory for the job actually exists. Return\n  \" early if the directory does not exist. This helps avoid errors when\n  \" working with plugins that use virtual files that don't actually exist on\n  \" the file system.\n  let l:filedir = expand(\"%:p:h\")\n  if has_key(l:options, 'cwd') && !isdirectory(l:options.cwd)\n      return\n  elseif !isdirectory(l:filedir)\n    return\n  endif\n\n  let l:manualcd = 0\n  if !has_key(l:options, 'cwd')\n    \" pre start\n    let l:manualcd = 1\n    let l:dir = go#util#Chdir(filedir)\n  endif\n\n  if has_key(l:options, '_start')\n    call l:options._start()\n    \" remove _start to play nicely with vim (when vim encounters an unexpected\n    \" job option it reports an \"E475: invalid argument\" error).\n    unlet l:options._start\n  endif\n\n  \" noblock was added in 8.1.350; remove it if it's not supported.\n  if has_key(l:options, 'noblock') && (has('nvim') || !has(\"patch-8.1.350\"))\n    call remove(l:options, 'noblock')\n  endif\n\n  if go#util#HasDebug('shell-commands')\n    call go#util#EchoInfo('job command: ' . string(a:cmd))\n  endif\n\n  if has('nvim')\n    let l:input = []\n    if has_key(a:options, 'in_io') && a:options.in_io ==# 'file' && !empty(a:options.in_name)\n      let l:input = readfile(a:options.in_name, \"b\")\n    endif\n\n    let job = jobstart(a:cmd, l:options)\n\n    if len(l:input) > 0\n      call chansend(job, l:input)\n      \" close stdin to signal that no more bytes will be sent.\n      call chanclose(job, 'stdin')\n    endif\n  else\n    let l:cmd = a:cmd\n    if go#util#IsWin()\n      let l:cmd = join(map(copy(a:cmd), function('s:winjobarg')), \" \")\n    endif\n\n    let job = job_start(l:cmd, l:options)\n  endif\n\n  if l:manualcd\n    \" post start\n    call go#util#Chdir(l:dir)\n  endif\n\n  return job\nendfunction\n\n\" s:neooptions returns a dictionary of job options suitable for use by Neovim\n\" based on a dictionary of job options suitable for Vim8.\nfunction! s:neooptions(options)\n  let l:options = {}\n  let l:options['stdout_buf'] = ''\n  let l:options['stderr_buf'] = ''\n\n  let l:err_mode = get(a:options, 'err_mode', get(a:options, 'mode', ''))\n  let l:out_mode = get(a:options, 'out_mode', get(a:options, 'mode', ''))\n\n  for key in keys(a:options)\n      if key == 'cwd'\n        let l:options['cwd'] = a:options['cwd']\n        continue\n      endif\n\n      if key == 'callback'\n        let l:options['callback'] = a:options['callback']\n\n        if !has_key(a:options, 'out_cb')\n          let l:options['on_stdout'] = function('s:callback2on_stdout', [l:out_mode], l:options)\n        endif\n\n        if !has_key(a:options, 'err_cb')\n          let l:options['on_stderr'] = function('s:callback2on_stderr', [l:err_mode], l:options)\n        endif\n\n        continue\n      endif\n\n      if key == 'out_cb'\n        let l:options['out_cb'] = a:options['out_cb']\n        let l:options['on_stdout'] = function('s:on_stdout', [l:out_mode], l:options)\n\n        continue\n      endif\n\n      if key == 'err_cb'\n        let l:options['err_cb'] = a:options['err_cb']\n        let l:options['on_stderr'] = function('s:on_stderr', [l:err_mode], l:options)\n\n        continue\n      endif\n\n      if key == 'exit_cb'\n        let l:options['exit_cb'] = a:options['exit_cb']\n        let l:options['on_exit'] = function('s:on_exit', [], l:options)\n\n        continue\n      endif\n\n      if key == 'close_cb'\n        continue\n      endif\n\n      if key == 'stoponexit'\n        if a:options['stoponexit'] == ''\n          let l:options['detach'] = 1\n        endif\n        continue\n      endif\n  endfor\n  return l:options\nendfunction\n\nfunction! s:callback2on_stdout(mode, ch, data, event) dict\n  let self.stdout_buf = s:neocb(a:mode, a:ch, self.stdout_buf, a:data, self.callback)\nendfunction\n\nfunction! s:callback2on_stderr(mode, ch, data, event) dict\n  let self.stderr_buf = s:neocb(a:mode, a:ch, self.stderr_buf, a:data, self.callback)\nendfunction\n\nfunction! s:on_stdout(mode, ch, data, event) dict\n  let self.stdout_buf = s:neocb(a:mode, a:ch, self.stdout_buf, a:data, self.out_cb)\nendfunction\n\nfunction! s:on_stderr(mode, ch, data, event) dict\n  let self.stderr_buf = s:neocb(a:mode, a:ch, self.stderr_buf, a:data, self.err_cb )\nendfunction\n\nfunction! s:on_exit(jobid, exitval, event) dict\n  call self.exit_cb(a:jobid, a:exitval)\nendfunction\n\nfunction! go#job#Stop(job) abort\n  if has('nvim')\n    call jobstop(a:job)\n    return\n  endif\n\n  call job_stop(a:job)\n  call go#job#Wait(a:job)\n  return\nendfunction\n\nfunction! go#job#Wait(job) abort\n  if has('nvim')\n    call jobwait([a:job])\n    return\n  endif\n\n  while job_status(a:job) is# 'run'\n    sleep 50m\n  endwhile\nendfunction\n\nfunction! s:winjobarg(idx, val) abort\n  if empty(a:val)\n    return '\"\"'\n  endif\n  return a:val\nendfunction\n\nfunction! s:neocb(mode, ch, buf, data, callback)\n  \" dealing with the channel lines of Neovim is awful. The docs (:help\n  \" channel-lines) say:\n  \"     stream event handlers may receive partial (incomplete) lines. For a\n  \"     given invocation of on_stdout etc, `a:data` is not guaranteed to end\n  \"     with a newline.\n  \"       - `abcdefg` may arrive as `['abc']`, `['defg']`.\n  \"       - `abc\\nefg` may arrive as `['abc', '']`, `['efg']` or `['abc']`,\n  \"         `['','efg']`, or even `['ab']`, `['c','efg']`.\n  \"\n  \" Thankfully, though, this is explained a bit better in an issue:\n  \" https://github.com/neovim/neovim/issues/3555. Specifically in these two\n  \" comments:\n  \"     * https://github.com/neovim/neovim/issues/3555#issuecomment-152290804\n  \"     * https://github.com/neovim/neovim/issues/3555#issuecomment-152588749\n  \"\n  \" The key is\n  \"     Every item in the list passed to job control callbacks represents a\n  \"     string after a newline(Except the first, of course). If the program\n  \"     outputs: \"hello\\nworld\" the corresponding list is [\"hello\", \"world\"].\n  \"     If the program outputs \"hello\\nworld\\n\", the corresponding list is\n  \"     [\"hello\", \"world\", \"\"]. In other words, you can always determine if\n  \"     the last line received is complete or not.\n  \" and\n  \"     for every list you receive in a callback, all items except the first\n  \"     represent newlines.\n\n  let l:buf = ''\n\n  \" A single empty string means EOF was reached. The first item will never be\n  \" an empty string except for when it's the only item and is signaling that\n  \" EOF was reached.\n  if len(a:data) == 1 && a:data[0] == ''\n    \" when there's nothing buffered, return early so that an\n    \" erroneous message will not be added.\n    if a:buf == ''\n      return ''\n    endif\n\n    let l:data = [a:buf]\n  else\n    let l:data = copy(a:data)\n    let l:data[0] = a:buf . l:data[0]\n\n    \" The last element may be a partial line; save it for next time.\n    if a:mode != 'raw'\n      let l:buf = l:data[-1]\n      let l:data = l:data[:-2]\n    endif\n  endif\n\n  let l:i = 0\n  let l:last = len(l:data) - 1\n  while l:i <= l:last\n    let l:msg = l:data[l:i]\n    if a:mode == 'raw' && l:i < l:last\n      let l:msg = l:msg . \"\\n\"\n    endif\n    if a:mode == 'raw'\n      call s:queueneocb(function(a:callback, [a:ch, l:msg]))\n    else\n      call a:callback(a:ch, l:msg)\n    endif\n\n    let l:i += 1\n  endwhile\n\n  return l:buf\nendfunction\n\n\" s:neocbs is used to workaround limitations of how Neovim limits the use of\n\" callbacks. This is particularly important when dealing with a raw channel\n\" whose data triggers further communication and more data on the channel and\n\" both the original response handler and the next response handler are\n\" awaited using go#promise (e.g. as is the case with go#lsp#Rename).\nlet s:neocbs = []\nfunction! s:dequeueneocbs(timer) abort\n  for l:Fn in s:neocbs\n    try\n      call remove(s:neocbs, 0)\n      call call(l:Fn, [])\n    finally\n    endtry\n  endfor\nendfunction\n\nfunction! s:queueneocb(fn) abort\n  let l:shouldStart = len(s:neocbs) == 0\n\n  let s:neocbs = add(s:neocbs, a:fn)\n\n  if l:shouldStart\n    call timer_start(10, function('s:dequeueneocbs', []))\n  endif\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/job_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunc! Test_JobDirWithSpaces()\n  if !go#util#has_job()\n    return\n  endif\n\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let l:filename = 'job/dir has spaces/main.go'\n    let l:tmp = gotest#load_fixture(l:filename)\n    call go#util#Chdir(printf('%s/src/job/dir has spaces', l:tmp))\n    call go#util#Exec(['go', 'mod', 'init', 'vim-go.test/job'])\n\n    \" set the compiler type so that the errorformat option will be set\n    \" correctly.\n    compiler go\n\n    let expected = [{'lnum': 4, 'bufnr': bufnr('%'), 'col': 2, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'undefined: notafunc'}]\n    \" clear the quickfix lists\n    call setqflist([], 'r')\n\n    \" go build discards any results when it compiles multiple packages. So we\n    \" pass the `errors` package just as a placeholder with the current folder\n    \" (indicated with '.').\n    let l:cmd = ['go', 'build', '.', 'errors']\n\n    let l:complete = go#promise#New(function('s:complete'), 10000, '')\n    call go#job#Spawn(l:cmd, {\n          \\ 'for': 'GoBuild',\n          \\ 'complete': l:complete.wrapper,\n          \\ 'statustype': 'build'\n         \\})\n\n    let l:out = l:complete.await()\n\n    let actual = getqflist()\n\n    call gotest#assert_quickfix(actual, l:expected)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! s:complete(job, exit_code, messages)\n  return a:messages\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/lint.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! go#lint#Gometa(bang, autosave, ...) abort\n  let l:metalinter = go#config#MetalinterCommand()\n\n  if a:0 == 0\n    let l:goargs = [expand('%:p:h')]\n    if l:metalinter == 'gopls' || l:metalinter == 'staticcheck'\n      let l:pkg = go#package#ImportPath()\n      if l:pkg == -1\n        call go#util#EchoError('could not determine package name')\n        return\n      endif\n\n      let l:goargs = [l:pkg]\n    endif\n  else\n    let l:goargs = a:000\n  endif\n\n  let l:cmd = []\n  let l:linters = a:autosave ? go#config#MetalinterAutosaveEnabled() : go#config#MetalinterEnabled()\n  if l:metalinter == 'golangci-lint'\n    let l:cmd = s:metalintercmd(l:metalinter, len(linters) != 0)\n    if empty(l:cmd)\n      return\n    endif\n\n    \" add linters to cmd\n    for l:linter in l:linters\n      let l:cmd += [\"--enable=\".l:linter]\n    endfor\n  elseif l:metalinter == 'staticcheck'\n    let l:cmd = s:metalintercmd(l:metalinter, 0)\n\n    if len(l:linters) > 0\n      let l:cmd += [printf('-checks=%s', join(l:linters, ',' ))]\n    endif\n  elseif l:metalinter != 'gopls'\n    \" the user wants something else, let us use it.\n    let l:cmd = split(go#config#MetalinterCommand(), \" \")\n  endif\n\n  if a:autosave\n    \" redraw so that any messages that were displayed while writing the file\n    \" will be cleared\n    redraw\n\n    let l:goargs[0] = expand('%:p')\n    if l:metalinter == 'staticcheck' || l:metalinter == \"golangci-lint\"\n      let l:goargs[0] = expand('%:p:h')\n    endif\n  endif\n\n  \" Call metalinter asynchronously.\n\n  if l:metalinter == 'golangci-lint'\n    let l:deadline = go#config#MetalinterDeadline()\n    if l:deadline != ''\n      let l:cmd += [\"--deadline=\" . l:deadline]\n    endif\n  endif\n\n  let l:cmd += l:goargs\n\n  let l:errformat = s:errorformat(l:metalinter)\n\n  if l:metalinter == 'gopls'\n    if a:autosave\n      let l:messages = go#lsp#AnalyzeFile(expand('%:p'))\n    else\n      let l:import_paths = l:goargs\n      let l:messages = call('go#lsp#Diagnostics', l:import_paths)\n    endif\n\n    let l:err = len(l:messages)\n  else\n    if go#util#has_job()\n      if a:autosave\n        let l:for = 'GoMetaLinterAutoSave'\n      else\n        let l:for = 'GoMetaLinter'\n      endif\n\n      call s:lint_job(l:metalinter, {'cmd': l:cmd, 'statustype': l:metalinter, 'errformat': l:errformat, 'for': l:for}, a:bang, a:autosave)\n      return\n    endif\n\n    let [l:out, l:err] = go#util#Exec(l:cmd)\n    let l:messages = split(out, \"\\n\")\n  endif\n\n  if a:autosave\n    let l:listtype = go#list#Type('GoMetaLinterAutoSave')\n    let l:for = 'GoMetaLinterAutoSave'\n  else\n    let l:listtype = go#list#Type('GoMetaLinter')\n    let l:for = 'GoMetaLinter'\n  endif\n\n  if l:err == 0\n    if !s:preserveerrors(a:autosave, l:listtype)\n      call go#list#Clean(l:listtype)\n    endif\n    call go#util#EchoSuccess('[metalinter] PASS')\n  else\n    let l:winid = win_getid(winnr())\n    \" Parse and populate our location list\n\n    if a:autosave\n      if l:metalinter == 'golangci-lint'\n        call s:metalinterautosavecomplete(l:metalinter, expand('%:p'), 0, 1, l:messages)\n      elseif l:metalinter == 'staticcheck'\n        call s:metalinterautosavecomplete(l:metalinter, fnamemodify(expand('%:p'), ':.'), 0, 1, l:messages)\n      endif\n    endif\n    call go#list#ParseFormat(l:listtype, l:errformat, l:messages, l:for, s:preserveerrors(a:autosave, l:listtype))\n\n    let errors = go#list#Get(l:listtype)\n    call go#list#Window(l:listtype, len(errors))\n\n    if a:autosave || a:bang\n      call win_gotoid(l:winid)\n    else\n      call go#list#JumpToFirst(l:listtype)\n    endif\n  endif\nendfunction\n\nfunction! go#lint#Diagnostics(bang, ...) abort\n  if a:0 == 0\n    let l:pkg = go#package#ImportPath()\n    if l:pkg == -1\n      call go#util#EchoError('could not determine package name')\n      return\n    endif\n\n    let l:import_paths = [l:pkg]\n  else\n    let l:import_paths = call('go#util#ExpandPattern', a:000)\n  endif\n\n  let l:errformat = s:errorformat('gopls')\n\n  let l:messages = call('go#lsp#Diagnostics', l:import_paths)\n\n  let l:listtype = go#list#Type(\"GoDiagnostics\")\n\n  \" Parse and populate the quickfix list\n  let l:winid = win_getid(winnr())\n  call go#list#ParseFormat(l:listtype, l:errformat, l:messages, 'GoDiagnostics', 0)\n\n  let l:errors = go#list#Get(l:listtype)\n\n  if len(l:errors) == 0\n    call go#list#Clean(l:listtype)\n    call go#util#EchoSuccess('[diagnostics] PASS')\n  else\n    call go#list#Window(l:listtype, len(errors))\n\n    if a:bang\n      call win_gotoid(l:winid)\n    else\n      call go#list#JumpToFirst(l:listtype)\n    endif\n  endif\nendfunction\n\n\" Golint calls 'golint' on the current directory. Any warnings are populated in\n\" the location list\nfunction! go#lint#Golint(bang, ...) abort\n  call go#cmd#autowrite()\n\n  let l:type = 'lint'\n  let l:status = {\n        \\ 'desc': 'current status',\n        \\ 'type': l:type,\n        \\ 'state': \"started\",\n        \\ }\n  if go#config#EchoCommandInfo()\n    call go#util#EchoProgress(printf('[%s] analyzing...', l:type))\n  endif\n  call go#statusline#Update(expand('%:p:h'), l:status)\n\n  if a:0 == 0\n    let [l:out, l:err] = go#util#Exec([go#config#GolintBin(), expand('%:p:h')])\n  else\n    let [l:out, l:err] = go#util#Exec([go#config#GolintBin()] + a:000)\n  endif\n\n  let l:status.state = 'success'\n  let l:state = 'PASS'\n  let l:listtype = go#list#Type(\"GoLint\")\n  if !empty(l:out)\n    let l:status.state = 'failed'\n    let l:state = 'FAIL'\n\n    let l:winid = win_getid(winnr())\n    call go#list#Parse(l:listtype, l:out, \"GoLint\", 0)\n    let l:errors = go#list#Get(l:listtype)\n    call go#list#Window(l:listtype, len(l:errors))\n\n    if a:bang\n      call win_gotoid(l:winid)\n    else\n      call go#list#JumpToFirst(l:listtype)\n    endif\n    if go#config#EchoCommandInfo()\n      call go#util#EchoError(printf('[%s] %s', l:type, l:state))\n    endif\n  else\n    call go#list#Clean(l:listtype)\n    if go#config#EchoCommandInfo()\n      call go#util#EchoSuccess(printf('[%s] %s', l:type, l:state))\n    endif\n  endif\n  call go#statusline#Update(expand('%:p:h'), l:status)\nendfunction\n\n\" Vet calls 'go vet' on the current buffer's directory. Any warnings are\n\" populated in the location list\nfunction! go#lint#Vet(bang, ...) abort\n  call go#cmd#autowrite()\n\n  let l:cmd = ['go', 'vet']\n\n  let buildtags = go#config#BuildTags()\n  if buildtags isnot ''\n    let l:cmd += ['-tags', buildtags]\n  endif\n\n  if a:0 == 0\n    let l:import_path = go#package#ImportPath()\n    if l:import_path == -1\n      call go#util#EchoError('could not determine package')\n      return\n    endif\n    let l:cmd = add(l:cmd, l:import_path)\n  else\n    let l:cmd = extend(l:cmd, a:000)\n  endif\n\n  let l:type = 'go vet'\n  if go#config#EchoCommandInfo()\n    call go#util#EchoProgress(printf('[%s] analyzing...', l:type))\n  endif\n  let l:status = {\n        \\ 'desc': 'current status',\n        \\ 'type': l:type,\n        \\ 'state': \"started\",\n        \\ }\n  call go#statusline#Update(expand('%:p:h'), l:status)\n\n  let [l:out, l:err] = go#util#ExecInDir(l:cmd)\n\n  let l:status.state = 'success'\n  let l:state = 'PASS'\n\n  let l:listtype = go#list#Type(\"GoVet\")\n  if l:err != 0\n    let l:status.state = 'failed'\n    let l:state = 'FAIL'\n\n    let l:winid = win_getid(winnr())\n    let l:errorformat = \"%-Gexit status %\\\\d%\\\\+,\" . &errorformat\n    let l:dir = go#util#Chdir(expand('%:p:h'))\n    try\n      call go#list#ParseFormat(l:listtype, l:errorformat, out, \"GoVet\", 0)\n    finally\n      call go#util#Chdir(l:dir)\n    endtry\n    let l:errors = go#list#Get(l:listtype)\n\n    if empty(l:errors)\n      call go#util#EchoError(l:out)\n      return\n    endif\n\n    call go#list#Window(l:listtype, len(l:errors))\n    if !empty(l:errors) && !a:bang\n      call go#list#JumpToFirst(l:listtype)\n    else\n      call win_gotoid(l:winid)\n    endif\n\n    if go#config#EchoCommandInfo()\n      call go#util#EchoError(printf('[%s] %s', l:type, l:state))\n    endif\n  else\n    call go#list#Clean(l:listtype)\n    if go#config#EchoCommandInfo()\n      call go#util#EchoSuccess(printf('[%s] %s', l:type, l:state))\n    endif\n  endif\n  call go#statusline#Update(expand('%:p:h'), l:status)\nendfunction\n\n\" ErrCheck calls 'errcheck' for the given packages. Any warnings are populated in\n\" the location list\nfunction! go#lint#Errcheck(bang, ...) abort\n  call go#cmd#autowrite()\n\n  let l:cmd = [go#config#ErrcheckBin(), '-abspath']\n\n  let buildtags = go#config#BuildTags()\n  if buildtags isnot ''\n    let l:cmd += ['-tags', buildtags]\n  endif\n\n  if a:0 == 0\n    let l:import_path = go#package#ImportPath()\n    if l:import_path == -1\n      call go#util#EchoError('could not determine package')\n      return\n    endif\n    let l:cmd = add(l:cmd, l:import_path)\n  else\n    let l:cmd = extend(l:cmd, a:000)\n  endif\n\n  let l:type = 'errcheck'\n  if go#config#EchoCommandInfo()\n    call go#util#EchoProgress(printf('[%s] analyzing...', l:type))\n  endif\n  let l:status = {\n        \\ 'desc': 'current status',\n        \\ 'type': l:type,\n        \\ 'state': \"started\",\n        \\ }\n  redraw\n\n  call go#statusline#Update(expand('%:p:h'), l:status)\n\n  let [l:out, l:err] = go#util#ExecInDir(l:cmd)\n\n  let l:status.state = 'success'\n  let l:state = 'PASS'\n\n  let l:listtype = go#list#Type(\"GoErrCheck\")\n  if l:err != 0\n    let l:status.state = 'failed'\n    let l:state = 'FAIL'\n\n    let l:winid = win_getid(winnr())\n\n    if l:err == 1\n      let l:errformat = \"%f:%l:%c:\\ %m,%f:%l:%c\\ %#%m\"\n      \" Parse and populate our location list\n      call go#list#ParseFormat(l:listtype, l:errformat, split(out, \"\\n\"), 'Errcheck', 0)\n    endif\n\n    let l:errors = go#list#Get(l:listtype)\n    if empty(l:errors)\n      call go#util#EchoError(l:out)\n      return\n    endif\n\n    if !empty(errors)\n      call go#list#Populate(l:listtype, l:errors, 'Errcheck')\n      call go#list#Window(l:listtype, len(l:errors))\n      if !a:bang\n        call go#list#JumpToFirst(l:listtype)\n      else\n        call win_gotoid(l:winid)\n      endif\n    endif\n    if go#config#EchoCommandInfo()\n      call go#util#EchoError(printf('[%s] %s', l:type, l:state))\n    endif\n  else\n    call go#list#Clean(l:listtype)\n    if go#config#EchoCommandInfo()\n      call go#util#EchoSuccess(printf('[%s] %s', l:type, l:state))\n    endif\n  endif\n  call go#statusline#Update(expand('%:p:h'), l:status)\nendfunction\n\nfunction! go#lint#ToggleMetaLinterAutoSave() abort\n  if go#config#MetalinterAutosave()\n    call go#config#SetMetalinterAutosave(0)\n    call go#util#EchoProgress(\"auto metalinter disabled\")\n    return\n  end\n\n  call go#config#SetMetalinterAutosave(1)\n  call go#util#EchoProgress(\"auto metalinter enabled\")\nendfunction\n\nfunction! s:lint_job(metalinter, args, bang, autosave)\n  let l:opts = {\n        \\ 'statustype': a:args.statustype,\n        \\ 'errorformat': a:args.errformat,\n        \\ 'for': 'GoMetaLinter',\n        \\ 'bang': a:bang,\n      \\ }\n\n  if a:autosave\n    let l:opts.for = 'GoMetaLinterAutoSave'\n    \" s:metalinterautosavecomplete is needed for staticcheck and golangci-lint\n    if a:metalinter == 'golangci-lint'\n      let l:opts.complete = funcref('s:metalinterautosavecomplete', [a:metalinter, expand('%:p')])\n    elseif a:metalinter == 'staticcheck'\n      let l:opts.complete = funcref('s:metalinterautosavecomplete', [a:metalinter, expand('%:p:t')])\n    endif\n    let l:opts.preserveerrors = funcref('s:preserveerrors', [a:autosave])\n  endif\n\n  \" autowrite is not enabled for jobs\n  call go#cmd#autowrite()\n\n  call go#job#Spawn(a:args.cmd, l:opts)\nendfunction\n\nfunction! s:metalintercmd(metalinter, haslinter)\n  let l:cmd = []\n  let l:bin_path = go#path#CheckBinPath(a:metalinter)\n  if !empty(l:bin_path)\n    if a:metalinter == \"golangci-lint\"\n      let l:cmd = s:golangcilintcmd(l:bin_path, a:haslinter)\n    elseif a:metalinter == 'staticcheck'\n      let l:cmd = [l:bin_path]\n    endif\n  endif\n\n  return l:cmd\nendfunction\n\nfunction! s:golangcilintcmd(bin_path, haslinter)\n  let l:cmd = [a:bin_path]\n  let l:cmd += [\"run\"]\n  let l:cmd += [\"--show-stats=false\"]\n  let l:cmd += [\"--output.text.print-issued-lines=false\"]\n  let l:cmd += ['--build-tags', go#config#BuildTags()]\n  let l:cmd += ['--path-mode', 'abs']\n  \" do not use the default exclude patterns, because doing so causes golint\n  \" problems about missing doc strings to be ignored and other things that\n  \" golint identifies.\n  \"let l:cmd += [\"--exclude-use-default=false\"]\n\n  if a:haslinter\n    let l:cmd += [\"--default=none\"]\n  endif\n\n  return l:cmd\nendfunction\n\nfunction! s:metalinterautosavecomplete(metalinter, filepath, job, exit_code, messages)\n  if !(a:metalinter == 'golangci-lint' || a:metalinter == 'staticcheck')\n    return\n  endif\n\n  if len(a:messages) == 0\n    return\n  endif\n\n  let l:pathRE = printf('^%s:', a:filepath)\n\n  let l:idx = 0\n  for l:item in a:messages\n    \" leave in any messages that report errors about a:filepath or that report\n    \" more general problems that prevent golangci-lint from linting\n    \" a:filepath.\n    \"\n    \" When given an absolute path to check, golangci-lint may return a lines\n    \" that are basically just a comment and provide the package name. Ignore\n    \" those.\n    \"\n    \" golangci-lint may provide a relative path to the file, so allow that,\n    \" too.\n    if (l:item =~#  l:pathRE && l:item !~# l:pathRE . ':\\d\\+: : # ') || (a:metalinter == 'golangci-lint' && l:item =~# '^level=')\n      let l:idx += 1\n      continue\n    endif\n\n    call remove(a:messages, l:idx)\n  endfor\nendfunction\n\nfunction! s:errorformat(metalinter) abort\n  if a:metalinter == 'golangci-lint'\n    \" Golangci-lint can output the following:\n    \"   <file>:<line>:<column>: <message> (<linter>)\n    \" This can be defined by the following errorformat:\n    return 'level=%tarning\\ msg=\"%m:\\ [%f:%l:%c:\\ %.%#]\",level=%tarning\\ msg=\"%m\",level=%trror\\ msg=\"%m:\\ [%f:%l:%c:\\ %.%#]\",level=%trror\\ msg=\"%m\",%-G%f:%l: : # %m,%f:%l:%c:\\ %m,%f:%l:\\ %m,%f:%l\\ %m'\n  elseif a:metalinter == 'staticcheck'\n    return '%f:%l:%c:\\ %m'\n  elseif a:metalinter == 'gopls'\n    let l:efm = ''\n    let l:level = go#config#DiagnosticsLevel()\n\n    if l:level == 0\n      return '%-G%f:%l:%c:%t:\\ %m,%-G%f:%l:%c::\\ %m,%-G%f:%l::%t:\\ %m'\n    endif\n\n    if l:level < 2\n      let l:efm = '%-G%f:%l:%c:W:\\ %m,%-G%f:%l::W:\\ %m,'\n    endif\n    return l:efm . '%f:%l:%c:%t:\\ %m,%f:%l:%c::\\ %m,%f:%l::%t:\\ %m'\n  endif\nendfunction\n\nfunction! s:preserveerrors(autosave, listtype) abort\n  return a:autosave && a:listtype == go#list#Type(\"GoFmt\") && go#config#FmtAutosave() && isdirectory(expand('%:p:h'))\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/lint_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunc! Test_GometaGolangciLint() abort\n  let g:go_gopls_enabled = 0\n  call s:gometa('golangci-lint')\nendfunc\n\nfunc! Test_GometaStaticcheck() abort\n  let g:go_gopls_enabled = 0\n  call s:gometa('staticcheck')\nendfunc\n\nfunc! s:gometa(metalinter) abort\n  let RestoreGOPATH = go#util#SetEnv('GOPATH', fnamemodify(getcwd(), ':p') . 'test-fixtures/lint')\n  call go#util#Chdir('test-fixtures/lint/src/foo')\n  silent exe 'e! ' . $GOPATH . '/src/foo/foo.go'\n\n  try\n    let g:go_metalinter_command = a:metalinter\n    let l:vim = s:vimdir()\n    let expected = [\n          \\ {'lnum': 1, 'bufnr': bufnr('%'), 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'at least one file in a package should have a package comment (ST1000)'},\n        \\ ]\n    if a:metalinter == 'golangci-lint'\n      let expected = [\n            \\ {'lnum': 1, 'bufnr': bufnr('%'), 'col': 1, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'package-comments: should have a package comment (revive)'},\n            \\ {'lnum': 5, 'bufnr': bufnr('%'), 'col': 1, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'exported: exported function MissingFooDoc should have comment or be unexported (revive)'}\n          \\ ]\n    endif\n\n    \" clear the quickfix list\n    call setqflist([], 'r')\n\n    let g:go_metalinter_enabled = ['ST1000']\n    if a:metalinter == 'golangci-lint'\n      let g:go_metalinter_enabled = ['revive']\n    endif\n\n    call go#lint#Gometa(0, 0, $GOPATH . '/src/foo')\n\n    let actual = getqflist()\n    let start = reltime()\n    while len(actual) == 0 && reltimefloat(reltime(start)) < 10\n      sleep 100m\n      let actual = copy(getqflist())\n    endwhile\n\n    \" sort the results, because golangci-lint doesn't always return notices in\n    \" a deterministic order.\n    call sort(l:actual)\n    call sort(l:expected)\n\n    call gotest#assert_quickfix(actual, expected)\n  finally\n      call call(RestoreGOPATH, [])\n  endtry\nendfunc\n\n\"func! Test_GometaGolangciLint_shadow() abort\n\"  call s:gometa_shadow('golangci-lint')\n\"endfunc\n\"\n\"func! s:gometa_shadow(metalinter) abort\n\"  let RestoreGOPATH = go#util#SetEnv('GOPATH', fnamemodify(getcwd(), ':p') . 'test-fixtures/lint')\n\"  silent exe 'e! ' . $GOPATH . '/src/lint/golangci-lint/problems/shadow/problems.go'\n\"\n\"  try\n\"    let g:go_metalinter_command = a:metalinter\n\"    let expected = [\n\"          \\ {'lnum': 4, 'bufnr': bufnr('%'), 'col': 7, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'module': '', 'text': '[runner] Can''t run linter golint: golint: analysis skipped: errors in package'},\n\"          \\ {'lnum': 4, 'bufnr': bufnr('%'), 'col': 7, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'e', 'module': '', 'text': 'Running error: golint: analysis skipped: errors in package'}\n\"        \\ ]\n\"\n\"    \" clear the quickfix list\n\"    call setqflist([], 'r')\n\"\n\"    let g:go_metalinter_enabled = ['golint']\n\"\n\"    call go#lint#Gometa(0, 0)\n\"\n\"    let actual = getqflist()\n\"    let start = reltime()\n\"    while len(actual) == 0 && reltimefloat(reltime(start)) < 10\n\"      sleep 100m\n\"      let actual = getqflist()\n\"    endwhile\n\"\n\"    call gotest#assert_quickfix(actual, expected)\n\"  finally\n\"      call call(RestoreGOPATH, [])\n\"  endtry\n\"endfunc\n\nfunc! Test_GometaAutoSaveGolangciLint() abort\n  let g:go_gopls_enabled = 0\n  call s:gometaautosave('golangci-lint', 0)\nendfunc\n\nfunc! Test_GometaAutoSaveStaticcheck() abort\n  let g:go_gopls_enabled = 0\n  call s:gometaautosave('staticcheck', 0)\nendfunc\n\nfunc! Test_GometaAutoSaveGopls() abort\n  let g:go_gopls_staticcheck = 1\n  let g:go_diagnostics_level = 2\n  call s:gometaautosave('gopls', 0)\nendfunc\n\nfunc! Test_GometaAutoSaveGolangciLintKeepsErrors() abort\n  let g:go_gopls_enabled = 0\n  call s:gometaautosave('golangci-lint', 1)\nendfunc\n\nfunc! Test_GometaAutoSaveStaticcheckKeepsErrors() abort\n  let g:go_gopls_enabled = 0\n  call s:gometaautosave('staticcheck', 1)\nendfunc\n\nfunc! s:gometaautosave(metalinter, withList) abort\n  let l:wd = getcwd()\n  let l:tmp = gotest#load_fixture('lint/src/lint/lint.go')\n\n  try\n    let g:go_metalinter_command = a:metalinter\n    let l:vim = s:vimdir()\n    let l:expected = [\n          \\ {'lnum': 1, 'bufnr': bufnr('%'), 'col': 1, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'at least one file in a package should have a package comment (ST1000)'},\n        \\ ]\n    if a:metalinter == 'gopls'\n      let l:expected = []\n\"      let l:expected = [\n\"            \\ {'lnum': 1, 'bufnr': bufnr('%'), 'col': 1, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'W', 'module': '', 'text': 'at least one file in a package should have a package comment'}\n\"          \\ ]\n    elseif a:metalinter == 'golangci-lint'\n      let l:expected = [\n            \\ {'lnum': 1, 'bufnr': bufnr('%'), 'col': 1, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'package-comments: should have a package comment (revive)'},\n            \\ {'lnum': 5, 'bufnr': bufnr('%'), 'col': 1, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'exported: exported function MissingDoc should have comment or be unexported (revive)'}\n          \\ ]\n    endif\n\n    let l:list = []\n    if a:withList\n      let l:list = [\n            \\ {'lnum': 1, 'bufnr': bufnr('%'), 'col': 1, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'before metalinter'}\n          \\ ]\n      let l:expected = extend(copy(l:list), l:expected)\n    endif\n\n    \" set the location list\n    call setloclist(0, l:list, 'r')\n\n    let g:go_metalinter_autosave_enabled = ['ST1000']\n    if a:metalinter == 'golangci-lint'\n      let g:go_metalinter_autosave_enabled = ['revive']\n    endif\n\n    call go#lint#Gometa(0, 1)\n\n    let l:actual = getloclist(0)\n    let l:start = reltime()\n    while len(l:actual) != len(l:expected) && reltimefloat(reltime(l:start)) < 10\n      sleep 100m\n      let l:actual = copy(getloclist(0))\n    endwhile\n\n    \" sort the results, because golangci-lint doesn't always return notices in\n    \" a deterministic order.\n    call sort(l:actual)\n    call sort(l:expected)\n\n    call gotest#assert_quickfix(l:actual, l:expected)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\n\"func! Test_GometaGolangciLint_importabs() abort\n\"  call s:gometa_importabs('golangci-lint')\n\"endfunc\n\"\n\"func! s:gometa_importabs(metalinter) abort\n\"  let RestoreGOPATH = go#util#SetEnv('GOPATH', fnamemodify(getcwd(), ':p') . 'test-fixtures/lint')\n\"  silent exe 'e! ' . $GOPATH . '/src/lint/golangci-lint/problems/importabs/problems.go'\n\"\n\"  try\n\"    let g:go_metalinter_command = a:metalinter\n\"\n\"    let expected = [\n\"          \\ {'lnum': 3, 'bufnr': bufnr('%'), 'col': 8, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': '\"/quux\" imported but not used (typecheck)'},\n\"        \\ ]\n\"    \" clear the quickfix list\n\"    call setqflist([], 'r')\n\"\n\"    let g:go_metalinter_enabled = ['revive', 'typecheck']\n\"\n\"    call go#lint#Gometa(0, 0)\n\"\n\"    let actual = getqflist()\n\"    let start = reltime()\n\"    while len(actual) == 0 && reltimefloat(reltime(start)) < 10\n\"      sleep 100m\n\"      let actual = copy(getqflist())\n\"    endwhile\n\"\n\"    \" sort the results, because golangci-lint doesn't always return notices in\n\"    \" a deterministic order.\n\"    call sort(l:actual)\n\"    call sort(l:expected)\n\"\n\"    call gotest#assert_quickfix(actual, expected)\n\"  finally\n\"      call call(RestoreGOPATH, [])\n\"  endtry\n\"endfunc\n\"\n\"func! Test_GometaAutoSaveGolangciLint_importabs() abort\n\"  call s:gometaautosave_importabs('golangci-lint')\n\"endfunc\n\"\n\"func! s:gometaautosave_importabs(metalinter) abort\n\"  let RestoreGOPATH = go#util#SetEnv('GOPATH', fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint')\n\"  silent exe 'e! ' . $GOPATH . '/src/lint/golangci-lint/problems/importabs/ok.go'\n\"\n\"  try\n\"    let g:go_metalinter_command = a:metalinter\n\"    let expected = [\n\"          \\ {'lnum': 3, 'bufnr': bufnr('%')+1, 'col': 8, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'module': '', 'text': '[runner] Can''t run linter golint: golint: analysis skipped: errors in package'},\n\"          \\ {'lnum': 3, 'bufnr': bufnr('%')+1, 'col': 8, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'e', 'module': '', 'text': 'Running error: golint: analysis skipped: errors in package'}\n\"        \\ ]\n\"\n\"    \" clear the location list\n\"    call setloclist(0, [], 'r')\n\"\n\"    let g:go_metalinter_autosave_enabled = ['golint']\n\"\n\"    call go#lint#Gometa(0, 1)\n\"\n\"    let actual = getloclist(0)\n\"    let start = reltime()\n\"    while len(actual) == 0 && reltimefloat(reltime(start)) < 10\n\"      sleep 100m\n\"      let actual = getloclist(0)\n\"    endwhile\n\"\n\"    call gotest#assert_quickfix(actual, expected)\n\"  finally\n\"    call call(RestoreGOPATH, [])\n\"  endtry\n\"endfunc\n\"\n\"func! Test_GometaGolangciLint_multiple() abort\n\"  call s:gometa_multiple('golangci-lint')\n\"endfunc\n\nfunc! s:gometa_multiple(metalinter) abort\n  let RestoreGOPATH = go#util#SetEnv('GOPATH', fnamemodify(getcwd(), ':p') . 'test-fixtures/lint')\n  silent exe 'e! ' . $GOPATH . '/src/lint/golangci-lint/problems/multiple/problems.go'\n\n  try\n    let g:go_metalinter_command = a:metalinter\n    let expected = [\n          \\ {'lnum': 4, 'bufnr': bufnr('%'), 'col': 2, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': '\"time\" imported and not used (typecheck)'},\n          \\ {'lnum': 8, 'bufnr': bufnr('%'), 'col': 24, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'time.Millisecond undefined (type int has no field or method Millisecond) (typecheck)'},\n          \\ {'lnum': 8, 'bufnr': bufnr('%'), 'col': 7, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'time.Sleep undefined (type int has no field or method Sleep) (typecheck)'},\n        \\ ]\n\n    \" clear the quickfix list\n    call setqflist([], 'r')\n\n    let g:go_metalinter_enabled = ['revive', 'typecheck']\n\n    call go#lint#Gometa(0, 0)\n\n    let actual = getqflist()\n    let start = reltime()\n    while len(actual) == 0 && reltimefloat(reltime(start)) < 10\n      sleep 100m\n      let actual = copy(getqflist())\n    endwhile\n\n    \" sort the results, because golangci-lint doesn't always return notices in\n    \" a deterministic order.\n    call sort(l:actual)\n    call sort(l:expected)\n\n    call gotest#assert_quickfix(actual, expected)\n  finally\n      call call(RestoreGOPATH, [])\n  endtry\nendfunc\n\n\"func! Test_GometaAutoSaveGolangciLint_multiple() abort\n\"  return\n\"  let g:go_gopls_enabled = 0\n\"  call s:gometaautosave_multiple('golangci-lint')\n\"endfunc\n\nfunc! s:gometaautosave_multiple(metalinter) abort\n  let RestoreGOPATH = go#util#SetEnv('GOPATH', fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint')\n  silent exe 'e! ' . $GOPATH . '/src/lint/golangci-lint/problems/multiple/problems.go'\n\n  try\n    let g:go_metalinter_command = a:metalinter\n    let expected = [\n          \\ {'lnum': 4, 'bufnr': bufnr('%'), 'col': 2, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': '\"time\" imported and not used'},\n          \\ {'lnum': 8, 'bufnr': bufnr('%'), 'col': 24, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'time.Millisecond undefined (type int has no field or method Millisecond)'},\n          \\ {'lnum': 8, 'bufnr': bufnr('%'), 'col': 7, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'time.Sleep undefined (type int has no field or method Sleep)'},\n        \\ ]\n\n    let [l:goversion, l:err] = go#util#Exec(['go', 'env', 'GOVERSION'])\n    let l:goversion = split(l:goversion, \"\\n\")[0]\n    if l:goversion < 'go1.20'\n      let expected = [\n            \\ {'lnum': 4, 'bufnr': bufnr('%'), 'col': 2, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'imported and not used: \"time\"'},\n            \\ {'lnum': 8, 'bufnr': bufnr('%'), 'col': 24, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'time.Millisecond undefined (type int has no field or method Millisecond) (typecheck)'},\n            \\ {'lnum': 8, 'bufnr': bufnr('%'), 'col': 7, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'time.Sleep undefined (type int has no field or method Sleep)'},\n          \\ ]\n    endif\n\n    \" clear the location list\n    call setloclist(0, [], 'r')\n\n    let g:go_metalinter_autosave_enabled = ['revive', 'typecheck']\n\n    call go#lint#Gometa(0, 1)\n\n    let actual = getloclist(0)\n    let start = reltime()\n    while len(actual) == 0 && reltimefloat(reltime(start)) < 10\n      sleep 100m\n      let actual = copy(getloclist(0))\n    endwhile\n\n\n    \" golangci-lint does not always return notices in a determinstic order and\n    \" at least with Go 1.20 removes only suffixes the last of the results from\n    \" a checker with the checker name. Therefore:\n    \" * strip off the checker name on Go 1.20 and above\n    \" * sort the results.\n    if l:goversion >= 'go1.20'\n      for l:error in l:actual\n        for l:key in keys(l:error)\n          if l:key == 'text'\n            let l:error[l:key] = substitute(l:error[l:key], ' (typecheck)', '', '')\n          endif\n        endfor\n      endfor\n    endif\n\n    call sort(l:actual)\n    call sort(l:expected)\n\n    call gotest#assert_quickfix(actual, expected)\n  finally\n    call call(RestoreGOPATH, [])\n  endtry\nendfunc\n\nfunc! Test_Vet() abort\n  let g:go_gopls_enabled = 0\n  let l:wd = getcwd()\n  let l:tmp = gotest#load_fixture('lint/src/vet/vet.go')\n\n  try\n    let expected = [\n          \\ {'lnum': 7, 'bufnr': bufnr('%'), 'col': 14, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'fmt.Printf format %d has arg str of wrong type string'}\n        \\ ]\n\n    let [l:goversion, l:err] = go#util#Exec(['go', 'env', 'GOVERSION'])\n    let l:goversion = split(l:goversion, \"\\n\")[0]\n    if l:goversion < 'go1.25'\n      let expected = [\n          \\ {'lnum': 7, 'bufnr': bufnr('%'), 'col': 2, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'fmt.Printf format %d has arg str of wrong type string'}\n          \\ ]\n    endif\n\n    let winnr = winnr()\n\n    \" clear the quickfix list\n    call setqflist([], 'r')\n\n    call go#lint#Vet(1)\n\n    let actual = getqflist()\n    let start = reltime()\n    while len(actual) == 0 && reltimefloat(reltime(start)) < 10\n      sleep 100m\n      let actual = getqflist()\n    endwhile\n\n    call gotest#assert_quickfix(actual, expected)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_Vet_subdir() abort\n  let g:go_gopls_enabled = 0\n  let l:wd = getcwd()\n  let l:tmp = gotest#load_fixture('lint/src/vet/vet.go')\n\n  \" go up one directory to easily test that go vet's file paths are handled\n  \" correctly when the working directory is not the directory that contains\n  \" the file being vetted.\n  call go#util#Chdir('..')\n\n  try\n    let expected = [\n          \\ {'lnum': 7, 'bufnr': bufnr('%'), 'col': 14, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'fmt.Printf format %d has arg str of wrong type string'}\n        \\ ]\n\n    let [l:goversion, l:err] = go#util#Exec(['go', 'env', 'GOVERSION'])\n    let l:goversion = split(l:goversion, \"\\n\")[0]\n    if l:goversion < 'go1.25'\n      let expected = [\n            \\ {'lnum': 7, 'bufnr': bufnr('%'), 'col': 2, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'fmt.Printf format %d has arg str of wrong type string'}\n          \\ ]\n    endif\n\n    let winnr = winnr()\n\n    \" clear the quickfix list\n    call setqflist([], 'r')\n\n    call go#lint#Vet(1)\n\n    let actual = getqflist()\n    let start = reltime()\n    while len(actual) == 0 && reltimefloat(reltime(start)) < 10\n      sleep 100m\n      let actual = getqflist()\n    endwhile\n\n    call gotest#assert_quickfix(actual, expected)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_Vet_compilererror() abort\n  let g:go_gopls_enabled = 0\n  let l:wd = getcwd()\n  let l:tmp = gotest#load_fixture('lint/src/vet/compilererror/compilererror.go')\n\n  try\n    let expected = [\n          \\ {'lnum': 6, 'bufnr': bufnr('%'), 'col': 22, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': \"missing ',' before newline in argument list (and 1 more errors)\"}\n        \\ ]\n\n    let winnr = winnr()\n\n    \" clear the quickfix list\n    call setqflist([], 'r')\n\n    call go#lint#Vet(1)\n\n    let actual = getqflist()\n    let start = reltime()\n    while len(actual) == 0 && reltimefloat(reltime(start)) < 10\n      sleep 100m\n      let actual = getqflist()\n    endwhile\n\n    call gotest#assert_quickfix(actual, expected)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! s:testLint() abort\n  silent exe 'e! ' . fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint/src/lint/baz.go'\n  silent exe 'e! ' . fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint/src/lint/quux.go'\n  silent exe 'e! ' . fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint/src/lint/lint.go'\n  compiler go\n\n  let expected = [\n          \\ {'lnum': 1, 'bufnr': bufnr('test-fixtures/lint/src/lint/baz.go'), 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'should have a package comment'},\n          \\ {'lnum': 5, 'bufnr': bufnr('%'), 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'exported function MissingDoc should have comment or be unexported'},\n          \\ {'lnum': 5, 'bufnr': bufnr('test-fixtures/lint/src/lint/quux.go'), 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'exported function AlsoMissingDoc should have comment or be unexported'}\n      \\ ]\n\n  let winnr = winnr()\n\n  \" clear the quickfix list\n  call setqflist([], 'r')\n\n  call go#lint#Golint(1)\n\n  let actual = getqflist()\n  let start = reltime()\n  while len(actual) == 0 && reltimefloat(reltime(start)) < 10\n    sleep 100m\n    let actual = getqflist()\n  endwhile\n\n  \" sort the results for deterministic ordering\n  call sort(actual)\n  call sort(expected)\n\n  call gotest#assert_quickfix(actual, expected)\nendfunc\n\nfunc! Test_Lint() abort\n  let g:go_gopls_enabled = 0\n  call s:testLint()\nendfunc\n\nfunc! Test_Lint_GOPATH() abort\n  let g:go_gopls_enabled = 0\n  let RestoreGO111MODULE = go#util#SetEnv('GO111MODULE', 'off')\n  let RestoreGOPATH = go#util#SetEnv('GOPATH', fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint')\n\n  call s:testLint()\n\n  call call(RestoreGOPATH, [])\n  call call(RestoreGO111MODULE, [])\nendfunc\n\nfunc! Test_Lint_NullModule() abort\n  let g:go_gopls_enabled = 0\n  let RestoreGO111MODULE = go#util#SetEnv('GO111MODULE', 'off')\n\n  call s:testLint()\n\n  call call(RestoreGO111MODULE, [])\nendfunc\n\nfunc! Test_Errcheck() abort\n  let g:go_gopls_enabled = 0\n  let RestoreGOPATH = go#util#SetEnv('GOPATH', fnamemodify(getcwd(), ':p') . 'test-fixtures/lint')\n  let RestoreGOFLAGS = go#util#SetEnv('GOFLAGS', \"-buildvcs=false\")\n  silent exe 'e! ' . $GOPATH . '/src/errcheck/errcheck.go'\n\n  try\n    let l:bufnr = bufnr('')\n    let expected = [\n          \\ {'lnum': 9, 'bufnr': bufnr(''), 'col': 9, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': \":\\tio.Copy(os.Stdout, os.Stdin)\"},\n          \\ {'lnum': 10, 'bufnr': bufnr('')+1, 'col': 9, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': \":\\tio.Copy(os.Stdout, os.Stdin)\"},\n        \\ ]\n\n    \" clear the quickfix list\n    call setqflist([], 'r')\n\n    call go#lint#Errcheck(1)\n\n    call gotest#assert_quickfix(getqflist(), expected)\n    call assert_equal(l:bufnr, bufnr(''))\n  finally\n    call call(RestoreGOFLAGS, [])\n    call call(RestoreGOPATH, [])\n  endtry\nendfunc\n\nfunc! Test_Errcheck_options() abort\n  let g:go_gopls_enabled = 0\n  let RestoreGOPATH = go#util#SetEnv('GOPATH', fnamemodify(getcwd(), ':p') . 'test-fixtures/lint')\n  silent exe 'e! ' . $GOPATH . '/src/errcheck/errcheck.go'\n\n  try\n    let l:bufnr = bufnr('')\n    let expected = [\n          \\ {'lnum': 9, 'bufnr': bufnr(''), 'col': 9, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': \":\\tio.Copy(os.Stdout, os.Stdin)\"},\n        \\ ]\n\n    \" clear the quickfix list\n    call setqflist([], 'r')\n\n    call go#lint#Errcheck(1, '-ignoretests')\n\n    call gotest#assert_quickfix(getqflist(), expected)\n    call assert_equal(l:bufnr, bufnr(''))\n  finally\n    call call(RestoreGOPATH, [])\n  endtry\nendfunc\n\nfunc! Test_Errcheck_compilererror() abort\n  let g:go_gopls_enabled = 0\n  let l:wd = getcwd()\n  let l:tmp = gotest#load_fixture('lint/src/errcheck/compilererror/compilererror.go')\n\n  try\n    let l:bufnr = bufnr('')\n    let expected = []\n\n    \" clear the quickfix list\n    call setqflist([], 'r')\n\n    call go#lint#Errcheck(1)\n\n    call gotest#assert_quickfix(getqflist(), expected)\n    call assert_equal(l:bufnr, bufnr(''))\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! s:vimdir()\n  let l:vim = \"vim-9.1\"\n  if has('nvim')\n    let l:vim = 'nvim'\n  elseif v:version == 820\n    let l:vim = 'vim-8.2'\n  endif\n\n  return l:vim\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/list.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\n\" Window opens the list with the given height up to 10 lines maximum.\n\" Otherwise g:go_loclist_height is used.\n\"\n\" If no or zero height is given it closes the window by default.\n\" To prevent this, set g:go_list_autoclose = 0\nfunction! go#list#Window(listtype, ...) abort\n  \" we don't use lwindow to close the location list as we need also the\n  \" ability to resize the window. So, we are going to use lopen and lclose\n  \" for a better user experience. If the number of errors in a current\n  \" location list increases/decreases, cwindow will not resize when a new\n  \" updated height is passed. lopen in the other hand resizes the screen.\n  if !a:0 || a:1 == 0\n    call go#list#Close(a:listtype)\n    return\n  endif\n\n  let height = go#config#ListHeight()\n  if height == 0\n    \" prevent creating a large location height for a large set of numbers\n    if a:1 > 10\n      let height = 10\n    else\n      let height = a:1\n    endif\n  endif\n\n  if a:listtype == \"locationlist\"\n    exe 'lopen ' . height\n  else\n    exe 'copen ' . height\n  endif\nendfunction\n\n\n\" Get returns the current items from the list\nfunction! go#list#Get(listtype) abort\n  if a:listtype == \"locationlist\"\n    return getloclist(0)\n  else\n    return getqflist()\n  endif\nendfunction\n\n\" Populate populate the list with the given items\nfunction! go#list#Populate(listtype, items, title) abort\n  if a:listtype == \"locationlist\"\n    call setloclist(0, a:items, 'r')\n    call setloclist(0, [], 'a', {'title': a:title})\n  else\n    call setqflist(a:items, 'r')\n    call setqflist([], 'a', {'title': a:title})\n  endif\nendfunction\n\n\" Parse parses the given items based on the specified errorformat and\n\" populates the list.\nfunction! go#list#ParseFormat(listtype, errformat, items, title, add) abort\n  \" backup users errorformat, will be restored once we are finished\n  let old_errorformat = &errorformat\n\n  \" parse and populate the location list\n  let &errorformat = a:errformat\n  try\n    call go#list#Parse(a:listtype, a:items, a:title, a:add)\n  finally\n    \"restore back\n    let &errorformat = old_errorformat\n  endtry\nendfunction\n\n\" Parse parses the given items based on the global errorformat and\n\" populates the list.\nfunction! go#list#Parse(listtype, items, title, add) abort\n  let l:list = []\n  if a:add\n    let l:list = go#list#Get(a:listtype)\n  endif\n\n  if a:listtype == \"locationlist\"\n    if a:add\n      laddexpr a:items\n    else\n      lgetexpr a:items\n    endif\n    call setloclist(0, [], 'a', {'title': a:title})\n  else\n    if a:add\n      caddexpr a:items\n    else\n      cgetexpr a:items\n    endif\n    call setqflist([], 'a', {'title': a:title})\n  endif\nendfunction\n\n\" JumpToFirst jumps to the first item in the location list\nfunction! go#list#JumpToFirst(listtype) abort\n  if a:listtype == \"locationlist\"\n    ll 1\n  else\n    cc 1\n  endif\nendfunction\n\n\" Clean cleans and closes the location list \nfunction! go#list#Clean(listtype) abort\n  if a:listtype == \"locationlist\"\n    lex []\n  else\n    cex []\n  endif\n\n  call go#list#Close(a:listtype)\nendfunction\n\n\" Close closes the location list\nfunction! go#list#Close(listtype) abort\n  let autoclose_window = go#config#ListAutoclose()\n  if !autoclose_window\n    return\n  endif\n\n  if a:listtype == \"locationlist\"\n    lclose\n  else\n    cclose\n  endif\nendfunction\n\nfunction! s:listtype(listtype) abort\n  let listtype = go#config#ListType()\n  if empty(listtype)\n    return a:listtype\n  endif\n\n  return listtype\nendfunction\n\n\" s:default_list_type_commands is the defaults that will be used for each of\n\" the supported commands (see documentation for g:go_list_type_commands). When\n\" defining a default, quickfix should be used if the command operates on\n\" multiple files, while locationlist should be used if the command operates on a\n\" single file or buffer. Keys that begin with an underscore are not supported\n\" in g:go_list_type_commands.\nlet s:default_list_type_commands = {\n      \\ \"GoBuild\":              \"quickfix\",\n      \\ \"GoDiagnostics\":        \"quickfix\",\n      \\ \"GoDebug\":              \"quickfix\",\n      \\ \"GoErrCheck\":           \"quickfix\",\n      \\ \"GoFmt\":                \"locationlist\",\n      \\ \"GoGenerate\":           \"quickfix\",\n      \\ \"GoInstall\":            \"quickfix\",\n      \\ \"GoLint\":               \"quickfix\",\n      \\ \"GoMetaLinter\":         \"quickfix\",\n      \\ \"GoMetaLinterAutoSave\": \"locationlist\",\n      \\ \"GoModFmt\":             \"locationlist\",\n      \\ \"GoModifyTags\":         \"locationlist\",\n      \\ \"GoRename\":             \"quickfix\",\n      \\ \"GoRun\":                \"quickfix\",\n      \\ \"GoTest\":               \"quickfix\",\n      \\ \"GoVet\":                \"quickfix\",\n      \\ \"GoReferrers\":          \"locationlist\",\n      \\ \"GoImplements\":         \"locationlist\",\n      \\ \"GoCallers\":            \"locationlist\",\n      \\ \"_term\":                \"locationlist\",\n      \\ \"_job\":                 \"locationlist\",\n  \\ }\n\nfunction! go#list#Type(for) abort\n  let l:listtype = s:listtype(get(s:default_list_type_commands, a:for))\n  if l:listtype == \"0\"\n    call go#util#EchoError(printf(\n          \\ \"unknown list type command value found ('%s'). Please open a bug report in the vim-go repo.\",\n          \\ a:for))\n    let l:listtype = \"quickfix\"\n  endif\n\n  return get(go#config#ListTypeCommands(), a:for, l:listtype)\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/lsp/completionitemkind.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nlet s:Text = 1\nlet s:Method = 2\nlet s:Function = 3\nlet s:Constructor = 4\nlet s:Field = 5\nlet s:Variable = 6\nlet s:Class = 7\nlet s:Interface = 8\nlet s:Module = 9\nlet s:Property = 10\nlet s:Unit = 11\nlet s:Value = 12\nlet s:Enum = 13\nlet s:Keyword = 14\nlet s:Snippet = 15\nlet s:Color = 16\nlet s:File = 17\nlet s:Reference = 18\nlet s:Folder = 19\nlet s:EnumMember = 20\nlet s:Constant = 21\nlet s:Struct = 22\nlet s:Event = 23\nlet s:Operator = 24\nlet s:TypeParameter = 25\n\nfunction! go#lsp#completionitemkind#Vim(kind) abort\n  if a:kind == s:Method || a:kind == s:Function || a:kind == s:Constructor\n    return 'f'\n  elseif a:kind == s:Variable || a:kind == s:Constant\n    return 'v'\n  elseif a:kind == s:Field || a:kind == s:Property\n    return 'm'\n  elseif a:kind == s:Class || a:kind == s:Interface || a:kind == s:Struct\n    return 't'\n  endif\nendfunction\n\nfunction! go#lsp#completionitemkind#IsFunction(kind) abort\n  if a:kind == s:Function\n    return 1\n  endif\n\n  return 0\nendfunction\n\nfunction! go#lsp#completionitemkind#IsMethod(kind) abort\n  if a:kind == s:Method\n    return 1\n  endif\n\n  return 0\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/lsp/filechangetype.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nlet s:fct = {\n  \\ 'Created': 1,\n  \\ 'Changed': 2,\n  \\ 'Deleted': 3,\n\\ }\n\nfunction! go#lsp#filechangetype#FileChangeType(name)\n\treturn s:fct[a:name]\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/lsp/lsp.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\n\" go#lsp#lsp#Position returns the LSP text position. If no arguments are\n\" provided, the cursor position is assumed. Otherwise, there should be two\n\" arguments: the line and the column.\nfunction! go#lsp#lsp#Position(...)\n  if a:0 < 2\n    let [l:line, l:col] = getpos('.')[1:2]\n  else\n    let l:line = a:1\n    let l:col = a:2\n  endif\n\n  \" LSP uses 0-based lines.\n  return [l:line - 1, s:character(l:line, l:col)]\nendfunction\n\nfunction! s:strlen(str) abort\n  let l:runes = split(a:str, '\\zs')\n  return len(l:runes) + len(filter(l:runes, 'char2nr(v:val)>=0x10000'))\nendfunction\n\nfunction! s:character(line, col) abort\n  return s:strlen(getline(a:line)[:col([a:line, a:col - 1])])\nendfunction\n\n\" go#lsp#PositionOf returns len(content[0:units]) where units is utf-16 code\n\" units. This is mostly useful for converting zero-based LSP text position to\n\" vim one-based position.\nfunction! go#lsp#lsp#PositionOf(content, units, ...) abort\n  if len(a:content) is 0\n    return 0\n  endif\n\n  let l:remaining = a:units\n  let l:str = ''\n  for l:rune in split(a:content, '\\zs')\n    if l:remaining <= 0\n      break\n    endif\n    let l:remaining -= 1\n    if char2nr(l:rune) >= 0x10000\n      let l:remaining -= 1\n    endif\n    let l:str = l:str . l:rune\n  endfor\n\n  return len(l:str) + 1\nendfunction\n\nfunction! go#lsp#lsp#SeverityToErrorType(severity) abort\n  if a:severity == 1\n    return 'E'\n  elseif a:severity == 2\n    return 'W'\n  elseif a:severity == 3\n    return 'I'\n  elseif a:severity == 4\n    return 'I'\n  endif\n\n  return ''\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/lsp/lsp_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nscriptencoding utf-8\n\nfunction! Test_PositionOf_Simple()\n  let l:actual = go#lsp#lsp#PositionOf(\"just ascii\", 3)\n  call assert_equal(4, l:actual)\nendfunc\n\nfunction! Test_PositionOf_Start()\n  let l:str = 'abcd'\n  let l:actual = go#lsp#lsp#PositionOf(l:str, 0)\n  call assert_equal(l:actual, 1)\n  \" subtract one, because PositionOf returns a one-based cursor position while\n  \" string indices are zero based.\n  call assert_equal(l:str[l:actual-1], 'a')\nendfunc\n\nfunction! Test_PositionOf_End()\n  let l:str = 'abcd'\n  let l:actual = go#lsp#lsp#PositionOf(l:str, 3)\n  call assert_equal(l:actual, 4)\n  \" subtract one, because PositionOf returns a one-based cursor position and\n  \" while string indices are zero based.\n  call assert_equal(l:str[l:actual-1], 'd')\nendfunc\n\nfunction! Test_PositionOf_MultiByte()\n  \" ⌘ is U+2318, which encodes to three bytes in utf-8 and 1 code unit in\n  \" utf-16.\n  let l:actual = go#lsp#lsp#PositionOf(\"⌘⌘ foo\", 3)\n  call assert_equal(8, l:actual)\nendfunc\n\nfunction! Test_PositionOf_MultipleCodeUnit()\n    \" 𐐀 is U+10400, which encodes to 4 bytes in utf-8 and 2 code units in\n    \" utf-16.\n    let l:actual = go#lsp#lsp#PositionOf(\"𐐀 bar\", 3)\n    call assert_equal(6, l:actual)\nendfunction\n\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/lsp/message.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! go#lsp#message#Initialize(wd) abort\n  return {\n          \\ 'notification': 0,\n          \\ 'method': 'initialize',\n          \\ 'params': {\n            \\ 'processId': getpid(),\n            \\ 'clientInfo': {\n              \\ 'name': 'vim-go',\n            \\ },\n            \\ 'rootUri': go#path#ToURI(a:wd),\n            \\ 'capabilities': {\n              \\ 'workspace': {\n                \\ 'workspaceFolders': v:true,\n                \\ 'didChangeConfiguration': {\n                  \\ 'dynamicRegistration': v:true,\n                \\ },\n                \\ 'workspaceEdit': {\n                \\   'documentChanges': v:true,\n                \\ },\n                \\ 'configuration': v:true,\n              \\ },\n              \\ 'textDocument': {\n                \\ 'hover': {\n                  \\ 'contentFormat': ['plaintext'],\n                \\ },\n                \\ 'completion': {\n                \\   'completionItem': {\n                \\     'snippetSupport': go#config#GoplsUsePlaceholders() ? v:true : v:false,\n                \\   },\n                \\ },\n                \\ 'codeAction': {\n                \\   'codeActionLiteralSupport': {\n                \\     'codeActionKind': {\n                \\       'valueSet': ['source.organizeImports', 'refactor.rewrite', 'refactor.extract'],\n                \\     },\n                \\   },\n                \\ },\n              \\ }\n            \\ },\n            \\ 'workspaceFolders': [s:workspaceFolder(0, a:wd)],\n          \\ }\n       \\ }\nendfunction\n\nfunction! go#lsp#message#Initialized() abort\n  return {\n          \\ 'notification': 1,\n          \\ 'method': 'initialized',\n          \\ 'params': {},\n       \\ }\nendfunction\n\nfunction! go#lsp#message#Shutdown() abort\n  return {\n          \\ 'notification': 0,\n          \\ 'method': 'shutdown',\n       \\ }\nendfunction\n\nfunction! go#lsp#message#Format(file) abort\n  return {\n          \\ 'notification': 0,\n          \\ 'method': 'textDocument/formatting',\n          \\ 'params': {\n          \\   'textDocument': {\n          \\       'uri': go#path#ToURI(a:file)\n          \\   },\n          \\   'options': {\n          \\     'insertSpaces': v:false,\n          \\   },\n          \\ }\n       \\ }\nendfunction\n\nfunction! go#lsp#message#CodeActionImports(file) abort\n  return s:codeAction('source.organizeImports', a:file)\nendfunction\n\nfunction! go#lsp#message#CodeActionFillStruct(file, line, col) abort\n  return go#lsp#message#CodeActionRefactor('rewrite', a:file, a:line, a:col, a:line, a:col)\nendfunction\n\nfunction! go#lsp#message#CodeActionRefactorExtract(file, startline, startcol, endline, endcol) abort\n  return go#lsp#message#CodeActionRefactor('extract', a:file, a:startline, a:startcol, a:endline, a:endcol)\nendfunction\n\nfunction! go#lsp#message#CodeActionRefactor(action, file, startline, startcol, endline, endcol) abort\n  let l:startpos = s:position(a:startline, a:startcol)\n  let l:endpos = s:position(a:endline, a:endcol)\n\n  let l:request = s:codeAction(printf('refactor.%s', a:action), a:file)\n\n  let l:request.params = extend(l:request.params,\n        \\ {\n          \\ 'range': {\n            \\ 'start': l:startpos,\n            \\ 'end': l:endpos,\n          \\ }\n        \\ })\n\n  return l:request\nendfunction\n\nfunction! s:codeAction(name, file) abort\n  return {\n          \\ 'notification': 0,\n          \\ 'method': 'textDocument/codeAction',\n          \\ 'params': {\n          \\   'textDocument': {\n          \\       'uri': go#path#ToURI(a:file)\n          \\   },\n          \\   'range': {\n          \\     'start': s:position(0, 0),\n          \\     'end': s:position(line('$'), 0),\n          \\   },\n          \\   'context': {\n          \\     'only': [a:name],\n          \\   },\n          \\ }\n       \\ }\nendfunction\n\nfunction! go#lsp#message#Exit() abort\n  return {\n          \\ 'notification': 1,\n          \\ 'method': 'exit',\n       \\ }\nendfunction\n\nfunction! go#lsp#message#WorkspaceFoldersResult(dirs) abort\n  return map(copy(a:dirs), function('s:workspaceFolder', []))\nendfunction\n\nfunction! go#lsp#message#Definition(file, line, col) abort\n  let l:params = s:textDocumentPositionParams(a:file,  a:line, a:col)\n  return {\n          \\ 'notification': 0,\n          \\ 'method': 'textDocument/definition',\n          \\ 'params': l:params,\n       \\ }\nendfunction\n\nfunction! go#lsp#message#TypeDefinition(file, line, col) abort\n  let l:params = s:textDocumentPositionParams(a:file,  a:line, a:col)\n  return {\n          \\ 'notification': 0,\n          \\ 'method': 'textDocument/typeDefinition',\n          \\ 'params': l:params,\n       \\ }\nendfunction\n\nfunction! go#lsp#message#Implementation(file, line, col) abort\n  let l:params = s:textDocumentPositionParams(a:file,  a:line, a:col)\n  return {\n          \\ 'notification': 0,\n          \\ 'method': 'textDocument/implementation',\n          \\ 'params': l:params,\n       \\ }\nendfunction\n\nfunction! go#lsp#message#DidOpen(file, content, version) abort\n  return {\n          \\ 'notification': 1,\n          \\ 'method': 'textDocument/didOpen',\n          \\ 'params': {\n          \\     'textDocument': {\n          \\         'uri': go#path#ToURI(a:file),\n          \\         'languageId': 'go',\n          \\         'text': a:content,\n          \\         'version': a:version,\n          \\     }\n          \\ }\n       \\ }\nendfunction\n\nfunction! go#lsp#message#DidChange(file, content, version) abort\n  return {\n          \\ 'notification': 1,\n          \\ 'method': 'textDocument/didChange',\n          \\ 'params': {\n          \\     'textDocument': {\n          \\         'uri': go#path#ToURI(a:file),\n          \\         'version': a:version,\n          \\     },\n          \\     'contentChanges': [\n          \\       {\n          \\         'text': a:content,\n          \\       }\n          \\     ]\n          \\ }\n       \\ }\nendfunction\n\nfunction! go#lsp#message#DidChangeWatchedFile(file, ct) abort\n  return {\n          \\ 'notification': 1,\n          \\ 'method': 'workspace/didChangeWatchedFiles',\n          \\ 'params': {\n          \\     'changes': [\n          \\       {\n          \\         'uri': go#path#ToURI(a:file),\n          \\         'type': go#lsp#filechangetype#FileChangeType(a:ct),\n          \\       },\n          \\     ],\n          \\ }\n       \\ }\nendfunction\n\nfunction! go#lsp#message#DidClose(file) abort\n  return {\n          \\ 'notification': 1,\n          \\ 'method': 'textDocument/didClose',\n          \\ 'params': {\n          \\     'textDocument': {\n          \\         'uri': go#path#ToURI(a:file),\n          \\     }\n          \\ }\n       \\ }\nendfunction\n\nfunction! go#lsp#message#Completion(file, line, col) abort\n  let l:params = s:textDocumentPositionParams(a:file,  a:line, a:col)\n  return {\n          \\ 'notification': 0,\n          \\ 'method': 'textDocument/completion',\n          \\ 'params': l:params,\n       \\ }\nendfunction\n\nfunction! go#lsp#message#References(file, line, col) abort\n  let l:params = s:textDocumentPositionParams(a:file,  a:line, a:col)\n  let l:params.context = {'includeDeclaration': v:true}\n  return {\n          \\ 'notification': 0,\n          \\ 'method': 'textDocument/references',\n          \\ 'params': l:params,\n       \\ }\nendfunction\n\nfunction! go#lsp#message#PrepareCallHierarchy(file, line, col) abort\n  let l:params = s:textDocumentPositionParams(a:file,  a:line, a:col)\n  return {\n          \\ 'notification': 0,\n          \\ 'method': 'textDocument/prepareCallHierarchy',\n          \\ 'params': l:params,\n       \\ }\nendfunction\n\nfunction! go#lsp#message#IncomingCalls(item) abort\n  return {\n          \\ 'notification': 0,\n          \\ 'method': 'callHierarchy/incomingCalls',\n          \\ 'params': {\n          \\   'item': a:item,\n          \\ }\n       \\ }\nendfunction\n\nfunction! go#lsp#message#Hover(file, line, col) abort\n  let l:params = s:textDocumentPositionParams(a:file,  a:line, a:col)\n  return {\n          \\ 'notification': 0,\n          \\ 'method': 'textDocument/hover',\n          \\ 'params': l:params,\n       \\ }\nendfunction\n\nfunction! go#lsp#message#Rename(file, line, col, newName) abort\n  let l:params = s:textDocumentPositionParams(a:file,  a:line, a:col)\n  let l:params.newName = a:newName\n  return {\n          \\ 'notification': 0,\n          \\ 'method': 'textDocument/rename',\n          \\ 'params': l:params,\n       \\ }\nendfunction\n\nfunction! go#lsp#message#ChangeWorkspaceFolders(add, remove) abort\n  let l:addDirs = map(copy(a:add), function('s:workspaceFolder', []))\n  let l:removeDirs = map(copy(a:remove), function('s:workspaceFolder', []))\n\n  return {\n          \\ 'notification': 1,\n          \\ 'method': 'workspace/didChangeWorkspaceFolders',\n          \\ 'params': {\n          \\   'event': {\n          \\     'removed': l:removeDirs,\n          \\     'added': l:addDirs,\n          \\     },\n          \\ }\n       \\ }\n\nendfunction\n\nfunction! go#lsp#message#ConfigurationResult(items) abort\n  let l:result = []\n\n  \" results must be in the same order as the items\n  for l:item in a:items\n    let l:workspace = go#path#FromURI(l:item.scopeUri)\n    let l:config = {\n          \\ 'buildFlags': [],\n          \\ 'hoverKind': 'Structured',\n          \\ }\n    let l:buildtags = go#config#BuildTags()\n    if buildtags isnot ''\n      let l:config.buildFlags = extend(l:config.buildFlags, ['-tags', go#config#BuildTags()])\n    endif\n\n    let l:deepCompletion = go#config#GoplsDeepCompletion()\n    let l:matcher = go#config#GoplsMatcher()\n    let l:completeUnimported = go#config#GoplsCompleteUnimported()\n    let l:staticcheck = go#config#GoplsStaticCheck()\n    let l:usePlaceholder = go#config#GoplsUsePlaceholders()\n    let l:tempModfile = go#config#GoplsTempModfile()\n    let l:analyses = go#config#GoplsAnalyses()\n    let l:local = go#config#GoplsLocal()\n    if type(l:local) is v:t_dict\n      let l:local = get(l:local, l:workspace, v:null)\n    endif\n    let l:gofumpt = go#config#GoplsGofumpt()\n    let l:settings = go#config#GoplsSettings()\n\n    if l:deepCompletion isnot v:null\n      if l:deepCompletion\n        let l:config.deepCompletion = v:true\n      else\n        let l:config.deepCompletion = v:false\n      endif\n    endif\n\n    if l:matcher isnot v:null\n        let l:config.matcher = l:matcher\n    endif\n\n    if l:completeUnimported isnot v:null\n      if l:completeUnimported\n        let l:config.completeUnimported = v:true\n      else\n        let l:config.completeUnimported = v:false\n      endif\n    endif\n\n    if l:staticcheck isnot v:null\n      if l:staticcheck\n        let l:config.staticcheck = v:true\n      else\n        let l:config.staticcheck = v:false\n      endif\n    endif\n\n    if l:usePlaceholder isnot v:null\n      if l:usePlaceholder\n        let l:config.usePlaceholders = v:true\n      else\n        let l:config.usePlaceholders = v:false\n      endif\n    endif\n\n    if l:tempModfile isnot v:null\n      if l:tempModfile\n        let l:config.tempModfile = v:true\n      else\n        let l:config.tempModfile = v:false\n      endif\n    endif\n\n    if l:analyses isnot v:null\n      let l:config.analyses = l:analyses\n    endif\n\n    if l:local isnot v:null\n        let l:config.local = l:local\n    endif\n\n    if l:gofumpt isnot v:null\n      if l:gofumpt\n        let l:config.gofumpt = v:true\n      else\n        let l:config.gofumpt = v:false\n      endif\n    endif\n\n    if l:settings isnot v:null\n      let l:config = extend(l:config, l:settings, 'keep')\n    endif\n\n    let l:result = add(l:result, deepcopy(l:config))\n  endfor\n\n  return l:result\nendfunction\n\nfunction! go#lsp#message#ExecuteCommand(cmd, args) abort\n  return {\n          \\ 'notification': 0,\n          \\ 'method': 'workspace/executeCommand',\n          \\ 'params': {\n          \\   'command': a:cmd,\n          \\   'arguments': a:args,\n          \\ }\n       \\ }\nendfunction\n\nfunction! go#lsp#message#ApplyWorkspaceEditResponse(ok) abort\n  return {\n          \\ 'applied': a:ok,\n       \\ }\nendfunction\n\nfunction! go#lsp#message#PrepareRename(file, line, col) abort\n  let l:params = s:textDocumentPositionParams(a:file,  a:line, a:col)\n  return {\n          \\ 'notification': 0,\n          \\ 'method': 'textDocument/prepareRename',\n          \\ 'params': l:params,\n       \\ }\nendfunction\n\nfunction! s:workspaceFolder(key, val) abort\n  return {'uri': go#path#ToURI(a:val), 'name': a:val}\nendfunction\n\nfunction! s:position(line, col) abort\n  return {'line': a:line, 'character': a:col}\nendfunction\n\nfunction! s:textDocumentPositionParams(fname, line, col) abort\n  return {\n          \\   'textDocument': {\n          \\       'uri': go#path#ToURI(a:fname)\n          \\   },\n          \\   'position': s:position(a:line, a:col),\n       \\ }\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/lsp.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nscriptencoding utf-8\n\nlet s:lspfactory = {}\n\nfunction! s:lspfactory.get() dict abort\n  if empty(get(self, 'current', {})) || empty(get(self.current, 'job', {}))\n    let self.current = s:newlsp()\n  endif\n\n  return self.current\nendfunction\n\nfunction! s:lspfactory.reset() dict abort\n  if has_key(self, 'current')\n    call remove(self, 'current')\n  endif\nendfunction\n\nfunction! s:newlsp() abort\n  \" job is the job used to talk to the backing instance of gopls.\n  \" ready is 0 until the initialize response has been received. 1 afterwards.\n  \" queue is messages to send after initialization\n  \" last_request_id is id of the most recently sent request.\n  \" buf is unprocessed/incomplete responses\n  \" handlers is a mapping of request ids to dictionaries of functions.\n  \"   request id -> {start, requestComplete, handleResult, error}\n  \"   * start is a function that takes no arguments\n  \"   * requestComplete is a function that takes 1 argument. The parameter will be 1\n  \"     if the call was succesful.\n  \"   * handleResult takes a single argument, the result message received from gopls\n  \"   * error takes a single argument, the error message received from gopls.\n  \"     The error method is optional.\n  \" workspaceDirectories is an array of named workspaces.\n  \" wd is the working directory for gopls\n  \" diagnostics is a dictionary whose keys are filenames and each value is a\n  \"   list of diagnostic messages for the file.\n  \" diagnosticsQueue is a queue of diagnostics notifications that have been\n  \"   received, but not yet processed.\n  \" fileVersions is a dictionary of filenames to versions.\n  \" notificationQueue is a dictionary of filenames to functions. For a given\n  \"   filename, each notification will call the first function in the list of\n  \"   function values and remove it from the list. The functions should accept\n  \"   two arguments: an absolute path and a list of diagnotics messages for\n  \"   the file.\n  let l:lsp = {\n        \\ 'job':  '',\n        \\ 'ready': 0,\n        \\ 'queue': [],\n        \\ 'last_request_id': 0,\n        \\ 'buf': '',\n        \\ 'handlers': {},\n        \\ 'workspaceDirectories': [],\n        \\ 'wd' : '',\n        \\ 'diagnosticsQueue': [],\n        \\ 'diagnostics': {},\n        \\ 'fileVersions': {},\n        \\ 'notificationQueue': {},\n        \\ }\n\n  if !go#config#GoplsEnabled()\n    let l:lsp.sendMessage = funcref('s:noop')\n    return l:lsp\n  endif\n\n  if !go#util#has_job()\n    let l:oldshortmess=&shortmess\n    if has('nvim')\n      set shortmess-=F\n    endif\n    call go#util#EchoWarning('Features that rely on gopls will not work without either Vim 8.0.0087 or newer with +job or Neovim')\n    \" Sleep one second to make sure people see the message. Otherwise it is\n    \" often immediately overwritten by an async message.\n    sleep 1\n    let &shortmess=l:oldshortmess\n    return l:lsp\n  endif\n\n  function! l:lsp.readMessage(data) dict abort\n    let l:responses = []\n    let l:rest = a:data\n\n    while 1\n      \" Look for the end of the HTTP headers\n      let l:body_start_idx = matchend(l:rest, \"\\r\\n\\r\\n\")\n\n      if l:body_start_idx < 0\n        \" incomplete header\n        break\n      endif\n\n      \" Parse the Content-Length header.\n      let l:header = l:rest[:l:body_start_idx - 4]\n      let l:length_match = matchlist(\n      \\   l:header,\n      \\   '\\vContent-Length: *(\\d+)'\n      \\)\n\n      if empty(l:length_match)\n        \" TODO(bc): shutdown gopls?\n        throw \"invalid JSON-RPC header:\\n\" . l:header\n      endif\n\n      \" get the start of the rest\n      let l:next_start_idx = l:body_start_idx + str2nr(l:length_match[1])\n\n      if len(l:rest) < l:next_start_idx\n        \" incomplete response body\n        break\n      endif\n\n      call s:debug('received', l:rest[:l:next_start_idx - 1])\n\n      let l:body = l:rest[l:body_start_idx : l:next_start_idx - 1]\n      let l:rest = l:rest[l:next_start_idx :]\n\n      try\n        \" add the json body to the list.\n        call add(l:responses, json_decode(l:body))\n      catch\n        \" TODO(bc): log the message and/or show an error message.\n      finally\n        \" intentionally left blank.\n      endtry\n    endwhile\n\n    return [l:rest, l:responses]\n  endfunction\n\n  function! l:lsp.handleMessage(ch, data) dict abort\n      let self.buf .= a:data\n\n      let [self.buf, l:messages] = self.readMessage(self.buf)\n\n      for l:message in l:messages\n        if has_key(l:message, 'method')\n          if has_key(l:message, 'id')\n            call self.handleRequest(l:message)\n          else\n            call self.handleNotification(l:message)\n          endif\n        elseif has_key(l:message, 'result') || has_key(l:message, 'error')\n          call self.handleResponse(l:message)\n        endif\n      endfor\n  endfunction\n\n  function! l:lsp.handleRequest(req) dict abort\n    if a:req.method == 'workspace/workspaceFolders'\n      let l:resp = go#lsp#message#WorkspaceFoldersResult(self.workspaceDirectories)\n    elseif a:req.method == 'workspace/configuration' && has_key(a:req, 'params') && has_key(a:req.params, 'items')\n      let l:resp = go#lsp#message#ConfigurationResult(a:req.params.items)\n    elseif a:req.method == 'client/registerCapability' && has_key(a:req, 'params') && has_key(a:req.params, 'registrations')\n      let l:resp = v:null\n    elseif a:req.method == 'workspace/applyEdit'\n      try\n        let l:ok = v:true\n        for l:change in a:req.params.edit.documentChanges\n          call s:applyDocumentChanges(a:req.params.edit.documentChanges)\n        endfor\n      catch\n        call go#util#EchoError(printf('could not apply edit: %s', v:exception))\n        let l:ok = v:false\n      endtry\n      let l:resp = go#lsp#message#ApplyWorkspaceEditResponse(l:ok)\n    else\n      return\n    endif\n\n    if get(self, 'exited', 0)\n      return\n    endif\n\n    let l:msg = self.newResponse(a:req.id, l:resp)\n    call self.write(l:msg)\n  endfunction\n\n  function! l:lsp.handleResponse(resp) dict abort\n    if has_key(a:resp, 'id') && has_key(self.handlers, a:resp.id)\n      try\n        let l:handler = self.handlers[a:resp.id]\n\n        let l:winid = win_getid(winnr())\n        \" Always set the active window to the window that was active when\n        \" the request was sent. Among other things, this makes sure that\n        \" the correct window's location list will be populated when the\n        \" list type is 'location' and the user has moved windows since\n        \" sending the request.\n        call win_gotoid(l:handler.winid)\n\n        if has_key(a:resp, 'error')\n          call l:handler.requestComplete(0)\n          if has_key(l:handler, 'error')\n            call call(l:handler.error, [a:resp.error.message])\n          else\n            call go#util#EchoError(a:resp.error.message)\n          endif\n          call win_gotoid(l:winid)\n          return\n        endif\n        call l:handler.requestComplete(1)\n\n        let l:winidBeforeHandler = l:handler.winid\n        call call(l:handler.handleResult, [a:resp.result])\n\n        \" change the window back to the window that was active when\n        \" starting to handle the message _only_ if the handler didn't\n        \" update the winid, so that handlers can set the winid if needed\n        \" (e.g. :GoDef).\n        if l:handler.winid == l:winidBeforeHandler\n          call win_gotoid(l:winid)\n        endif\n      finally\n        call remove(self.handlers, a:resp.id)\n      endtry\n    endif\n  endfunction\n\n  function! l:lsp.handleNotification(req) dict abort\n      \" TODO(bc): handle more notifications (e.g. window/showMessage).\n      if a:req.method == 'textDocument/publishDiagnostics'\n        call self.handleDiagnostics(a:req.params)\n      elseif a:req.method == 'window/showMessage'\n        call self.showMessage(a:req.params)\n      endif\n  endfunction\n\n  function! l:lsp.handleDiagnostics(data) dict abort\n    let self.diagnosticsQueue = add(self.diagnosticsQueue, a:data)\n    call self.updateDiagnostics()\n  endfunction\n\n  function! l:lsp.showMessage(data) dict abort\n    let l:msg = a:data.message\n    if a:data.type == 1\n      call go#util#EchoError(l:msg)\n    elseif a:data.type == 2\n      call go#util#EchoWarning(l:msg)\n    elseif a:data.type == 3\n      call go#util#EchoInfo(l:msg)\n    elseif a:data.type == 4\n      \" do nothing for Log messages\n    endif\n  endfunction\n\n  \" TODO(bc): process the queue asynchronously\n  function! l:lsp.updateDiagnostics() dict abort\n    let l:level = go#config#DiagnosticsLevel()\n\n    for l:data in self.diagnosticsQueue\n      call remove(self.diagnosticsQueue, 0)\n\n      try\n        let l:diagnostics = []\n        let l:errorMatches = []\n        let l:warningMatches = []\n        let l:fname = go#path#FromURI(l:data.uri)\n\n        \" get the buffer name relative to the current directory, because\n        \" Vim says that a buffer name can't be an absolute path.\n        let l:bufname = fnamemodify(l:fname, ':.')\n\n        if len(l:data.diagnostics) > 0 && (l:level > 0 || bufnr(l:bufname) == bufnr(''))\n          \" make sure the buffer is listed and loaded before calling getbufline() on it\n          if !bufexists(l:bufname)\n            call bufadd(l:bufname)\n          endif\n\n          if !bufloaded(l:bufname)\n            call bufload(l:bufname)\n          endif\n\n          for l:diag in l:data.diagnostics\n            if l:level < l:diag.severity\n              continue\n            endif\n            let [l:diagnostic, l:matchpos] = s:processDiagnostic(l:diag, l:bufname, l:fname)\n            let l:diagnostics = add(l:diagnostics, l:diagnostic)\n\n            if empty(l:matchpos)\n              continue\n            endif\n\n            if l:diag.severity == 1\n              let l:errorMatches = add(l:errorMatches, l:matchpos)\n            elseif l:diag.severity == 2\n              let l:warningMatches = add(l:warningMatches, l:matchpos)\n            endif\n          endfor\n        endif\n\n        if bufnr(l:bufname) == bufnr('')\n          \" only apply highlighting when the diagnostics are for the current\n          \" version.\n          let l:lsp = s:lspfactory.get()\n          let l:version = get(l:lsp.fileVersions, l:fname, 0)\n          \" it's tempting to only highlight matches when they are for the\n          \" current version of the buffer, but that causes problems when the\n          \" version number has been updated and the content has not. In such a\n          \" case, the diagnostics may not be sent for later versions.\n          call s:highlightMatches(l:errorMatches, l:warningMatches)\n        endif\n\n        let self.diagnostics[l:fname] = l:diagnostics\n        if has_key(self.notificationQueue, l:fname) && len(self.notificationQueue[l:fname]) > 0\n          call call(self.notificationQueue[l:fname][0], copy(l:diagnostics))\n          call remove(self.notificationQueue[l:fname], 0)\n        endif\n      catch\n        \"call go#util#EchoError(printf('%s: %s', v:throwpoint, v:exception))\n      endtry\n    endfor\n  endfunction\n\n  function! l:lsp.handleInitializeResult(result) dict abort\n    if go#config#EchoCommandInfo()\n      call go#util#EchoProgress(\"initialized gopls\")\n    endif\n    let status = {\n          \\ 'desc': '',\n          \\ 'type': 'gopls',\n          \\ 'state': 'initialized',\n        \\ }\n    call go#statusline#Update(self.wd, status)\n\n    let self.ready = 1\n    let  l:msg = self.newMessage(go#lsp#message#Initialized())\n    call self.write(l:msg)\n\n    \" send messages queued while waiting for ready.\n    for l:item in self.queue\n      call self.sendMessage(l:item.data, l:item.handler)\n    endfor\n\n    \" reset the queue\n    let self.queue = []\n  endfunction\n\n  function! l:lsp.sendMessage(data, handler) dict abort\n    if !self.last_request_id\n      let l:wd = go#util#ModuleRoot()\n      if l:wd == -1\n        call go#util#EchoError('could not determine appropriate working directory for gopls')\n        return -1\n      endif\n\n      if l:wd == ''\n        let l:wd = getcwd()\n      endif\n      let self.wd = l:wd\n\n      if go#config#EchoCommandInfo()\n        call go#util#EchoProgress(\"initializing gopls\")\n      endif\n\n      let l:status = {\n            \\ 'desc': '',\n            \\ 'type': 'gopls',\n            \\ 'state': 'initializing',\n          \\ }\n      call go#statusline#Update(l:wd, l:status)\n\n      let self.workspaceDirectories = s:dedup(add(self.workspaceDirectories, l:wd))\n      let l:msg = self.newMessage(go#lsp#message#Initialize(l:wd))\n\n      let l:state = s:newHandlerState('')\n      let l:state.handleResult = funcref('self.handleInitializeResult', [], l:self)\n\n      let self.handlers[l:msg.id] = l:state\n\n      call l:state.start()\n      call self.write(l:msg)\n    endif\n\n    if !self.ready\n      call add(self.queue, {'data': a:data, 'handler': a:handler})\n      return\n    endif\n\n    let l:msg = self.newMessage(a:data)\n    if has_key(l:msg, 'id')\n      let self.handlers[l:msg.id] = a:handler\n    endif\n\n    call a:handler.start()\n    call self.write(l:msg)\n  endfunction\n\n  \" newMessage returns a message constructed from data. data should be a dict\n  \" with 2 or 3 keys: notification, method, and optionally params.\n  function! l:lsp.newMessage(data) dict abort\n    let l:msg = {\n          \\ 'method': a:data.method,\n          \\ 'jsonrpc': '2.0',\n        \\ }\n\n    if !a:data.notification\n      let self.last_request_id += 1\n      let l:msg.id = self.last_request_id\n    endif\n\n    if has_key(a:data, 'params')\n      let l:msg.params = a:data.params\n    endif\n\n    return l:msg\n  endfunction\n\n  function l:lsp.newResponse(id, result) dict abort\n    let l:msg = {\n          \\ 'jsonrpc': '2.0',\n          \\ 'id': a:id,\n          \\ 'result': a:result,\n        \\ }\n\n    return l:msg\n  endfunction\n\n  function! l:lsp.write(msg) dict abort\n    if empty(get(self, 'job', {}))\n      return\n    endif\n\n    let l:body = json_encode(a:msg)\n    let l:data = 'Content-Length: ' . strlen(l:body) . \"\\r\\n\\r\\n\" . l:body\n\n    call s:debug('sent', l:data)\n\n    if has('nvim')\n      call chansend(self.job, l:data)\n      return\n    endif\n\n    try\n      call ch_sendraw(self.job, l:data)\n    catch\n      call go#util#EchoError(printf('could not send message: %s', v:exception))\n    endtry\n  endfunction\n\n  function! l:lsp.exit_cb(job, exit_status) dict\n    let self.exited = 1\n    if !get(self, 'restarting', 0)\n      return\n    endif\n\n    let l:queue = self.queue\n\n    let l:workspaces = self.workspaceDirectories\n\n    call s:lspfactory.reset()\n    let l:lsp = s:lspfactory.get()\n\n    \" restore workspaces\n    call call('go#lsp#AddWorkspaceDirectory', l:workspaces)\n    \" * send DidOpen messages for all buffers that have b:did_lsp_open set\n    \" TODO(bc): check modifiable and filetype, too?\n    bufdo! if get(b:, 'go_lsp_did_open', 0) | let b:go_lsp_did_open = 0 | if &modified | call go#lsp#DidOpen(expand('%:p')) | else | call go#lsp#DidChange(expand('%:p')) | endif | endif\n    let l:lsp.queue = extend(l:lsp.queue, l:queue)\n    return\n  endfunction\n\n  function! l:lsp.close_cb(ch) dict abort\n    \" TODO(bc): remove the buffer variables that indicate that gopls has been\n    \" informed that the file is open\n  endfunction\n\n  function! l:lsp.err_cb(ch, msg) dict abort\n    if !get(self, 'debugport', 0)\n      if a:msg =~ '.*debug server listening at http://localhost:\\d\\+$' \" current log for debug server\n        let self.debugport = substitute(a:msg, '.*debug server listening at http://localhost:\\(\\d\\+\\)$', '\\1', '')\n      elseif a:msg =~ '^\\d\\{4}/\\d\\d/\\d\\d\\ \\d\\d:\\d\\d:\\d\\d debug server listening on port \\d\\+$' \" old gopls log for debug server\n        let self.debugport = substitute(a:msg, '\\d\\{4}/\\d\\d/\\d\\d\\ \\d\\d:\\d\\d:\\d\\d debug server listening on port \\(\\d\\+\\).*$', '\\1', '')\n      endif\n    endif\n\n    call s:debug('stderr', a:msg)\n  endfunction\n\n  \" explicitly bind callbacks to l:lsp so that within it, self will always refer\n  \" to l:lsp instead of l:opts. See :help Partial for more information.\n  let l:opts = {\n        \\ 'in_mode': 'raw',\n        \\ 'out_mode': 'raw',\n        \\ 'err_mode': 'nl',\n        \\ 'noblock': 1,\n        \\ 'err_cb': funcref('l:lsp.err_cb', [], l:lsp),\n        \\ 'out_cb': funcref('l:lsp.handleMessage', [], l:lsp),\n        \\ 'close_cb': funcref('l:lsp.close_cb', [], l:lsp),\n        \\ 'exit_cb': funcref('l:lsp.exit_cb', [], l:lsp),\n        \\ 'cwd': getcwd(),\n        \\}\n\n  let l:bin_path = go#path#CheckBinPath(\"gopls\")\n  if empty(l:bin_path)\n    let l:lsp.sendMessage = funcref('s:noop')\n    return l:lsp\n  endif\n\n  let l:cmd = [l:bin_path]\n  let l:cmdopts = go#config#GoplsOptions()\n\n  if go#util#HasDebug('lsp')\n    \" debugging can be enabled either with g:go_debug or with\n    \" g:go_gopls_options; use g:go_gopls_options if it's given in case users\n    \" are running the gopls debug server on a known port.\n    let l:needsDebug = 1\n\n    for l:item in l:cmdopts\n      let l:idx = stridx(l:item, '-debug')\n      if l:idx == 0 || l:idx == 1\n        let l:needsDebug = 0\n      endif\n    endfor\n    if l:needsDebug\n      let l:cmd = extend(l:cmd, ['-debug', 'localhost:0'])\n    endif\n  endif\n\n  let l:lsp.job = go#job#Start(l:cmd+l:cmdopts, l:opts)\n\n  return l:lsp\nendfunction\n\nfunction! s:noop(...) abort\nendfunction\n\nfunction! s:newHandlerState(statustype) abort\n  let l:state = {\n        \\ 'winid': win_getid(winnr()),\n        \\ 'statustype': a:statustype,\n        \\ 'jobdir': getcwd(),\n        \\ 'handleResult': funcref('s:noop'),\n      \\ }\n\n  \" explicitly bind requestComplete to state so that within it, self will\n  \" always refer to state. See :help Partial for more information.\n  let l:state.requestComplete = funcref('s:requestComplete', [], l:state)\n\n  \" explicitly bind start to state so that within it, self will\n  \" always refer to state. See :help Partial for more information.\n  let l:state.start = funcref('s:start', [], l:state)\n\n  return l:state\nendfunction\n\nfunction! s:requestComplete(ok) abort dict\n  if self.statustype == ''\n    return\n  endif\n\n  if go#config#EchoCommandInfo()\n    \" redraw to avoid messages piling up\n    redraw\n    let prefix = '[' . self.statustype . '] '\n    if a:ok\n      call go#util#EchoSuccess(prefix . \"SUCCESS\")\n    else\n      call go#util#EchoError(prefix . \"FAIL\")\n    endif\n  endif\n\n  let status = {\n        \\ 'desc': 'last status',\n        \\ 'type': self.statustype,\n        \\ 'state': \"success\",\n        \\ }\n\n  if !a:ok\n    let status.state = \"failed\"\n  endif\n\n  if has_key(self, 'started_at')\n    let elapsed_time = reltimestr(reltime(self.started_at))\n    \" strip whitespace\n    let elapsed_time = substitute(elapsed_time, '^\\s*\\(.\\{-}\\)\\s*$', '\\1', '')\n    let status.state .= printf(\" (%ss)\", elapsed_time)\n  endif\n\n  call go#statusline#Update(self.jobdir, status)\nendfunction\n\nfunction! s:start() abort dict\n  let self.started_at = reltime()\n  if self.statustype == ''\n    return\n  endif\n  let status = {\n        \\ 'desc': 'current status',\n        \\ 'type': self.statustype,\n        \\ 'state': \"started\",\n        \\ }\n\n  call go#statusline#Update(self.jobdir, status)\nendfunction\n\n\" go#lsp#Definition calls gopls to get the definition of the identifier at\n\" line and col in fname. handler should be a dictionary function that takes a\n\" list of strings in the form 'file:line:col: message'. handler will be\n\" attached to a dictionary that manages state (statuslines, sets the winid,\n\" etc.)\nfunction! go#lsp#Definition(fname, line, col, handler) abort\n  call go#lsp#DidChange(a:fname)\n\n  let l:lsp = s:lspfactory.get()\n  let l:state = s:newHandlerState('definition')\n  let l:state.handleResult = funcref('s:definitionHandler', [function(a:handler, [], l:state)], l:state)\n  let l:msg = go#lsp#message#Definition(fnamemodify(a:fname, ':p'), a:line, a:col)\n  return l:lsp.sendMessage(l:msg, l:state)\nendfunction\n\nfunction! s:definitionHandler(next, msg) abort dict\n  if a:msg is v:null || len(a:msg) == 0\n    return\n  endif\n\n  \" gopls returns a []Location; just take the first one.\n  let l:msg = a:msg[0]\n\n  let l:line = s:lineinfile(go#path#FromURI(l:msg.uri), l:msg.range.start.line+1)\n  if l:line is -1\n    call go#util#EchoWarning('could not find definition')\n    return\n  endif\n\n  let l:args = [[printf('%s:%d:%d: %s', go#path#FromURI(l:msg.uri), l:msg.range.start.line+1, go#lsp#lsp#PositionOf(l:line, l:msg.range.start.character), 'lsp does not supply a description')]]\n  call call(a:next, l:args)\nendfunction\n\n\" go#lsp#Type calls gopls to get the type definition of the identifier at\n\" line and col in fname. handler should be a dictionary function that takes a\n\" list of strings in the form 'file:line:col: message'. handler will be\n\" attached to a dictionary that manages state (statuslines, sets the winid,\n\" etc.)\nfunction! go#lsp#TypeDef(fname, line, col, handler) abort\n  call go#lsp#DidChange(a:fname)\n\n  let l:lsp = s:lspfactory.get()\n  let l:state = s:newHandlerState('type definition')\n  let l:msg = go#lsp#message#TypeDefinition(fnamemodify(a:fname, ':p'), a:line, a:col)\n  let l:state.handleResult = funcref('s:typeDefinitionHandler', [function(a:handler, [], l:state)], l:state)\n  return l:lsp.sendMessage(l:msg, l:state)\nendfunction\n\nfunction! s:typeDefinitionHandler(next, msg) abort dict\n  if a:msg is v:null || len(a:msg) == 0\n    return\n  endif\n\n  \" gopls returns a []Location; just take the first one.\n  let l:msg = a:msg[0]\n\n  let l:line = s:lineinfile(go#path#FromURI(l:msg.uri), l:msg.range.start.line+1)\n  if l:line is -1\n    call go#util#EchoWarning('could not find definition')\n    return\n  endif\n\n  let l:args = [[printf('%s:%d:%d: %s', go#path#FromURI(l:msg.uri), l:msg.range.start.line+1, go#lsp#lsp#PositionOf(l:line, l:msg.range.start.character), 'lsp does not supply a description')]]\n  call call(a:next, l:args)\nendfunction\n\n\" go#lsp#Callers calls gopls to get callers of the identifier at\n\" line and col in fname. handler should be a dictionary function that takes a\n\" list of strings in the form 'file:line:col: message'. handler will be\n\" attached to a dictionary that manages state (statuslines, sets the winid,\n\" etc.)\nfunction! go#lsp#Callers(fname, line, col, handler) abort\n  call go#lsp#DidChange(a:fname)\n\n  let l:lsp = s:lspfactory.get()\n  let l:state = s:newHandlerState('callers')\n  let l:msg = go#lsp#message#PrepareCallHierarchy(fnamemodify(a:fname, ':p'), a:line, a:col)\n  let l:state.handleResult = funcref('s:prepareCallHierarchyHandler', [function(a:handler, [], l:state)], l:state)\n  return l:lsp.sendMessage(l:msg, l:state)\nendfunction\n\nfunction! s:prepareCallHierarchyHandler(next, msg) abort dict\n  if a:msg is v:null || len(a:msg) == 0\n    return\n  endif\n\n  let l:lsp = s:lspfactory.get()\n  let l:state = s:newHandlerState('callers')\n  let l:msg = go#lsp#message#IncomingCalls(a:msg[0])\n  let l:state.handleResult = funcref('s:incomingCallsHandler', [function(a:next, [], l:state)], l:state)\n  return l:lsp.sendMessage(l:msg, l:state)\nendfunction\n\nfunction! s:incomingCallsHandler(next, msg) abort dict\n  if a:msg is v:null || len(a:msg) == 0\n    return\n  endif\n\n  let l:locations = []\n  for l:item in a:msg\n    try\n      let l:fname = go#path#FromURI(l:item.from.uri)\n\n      for l:fromRange in l:item.fromRanges\n        let l:line = l:fromRange.start.line+1\n        let l:content = s:lineinfile(l:fname, l:line)\n        if l:content is -1\n          continue\n        endif\n        let l:locations = add(l:locations, printf('%s:%s:%s: %s', l:fname, l:line, go#lsp#lsp#PositionOf(content, l:fromRange.start.character), l:item.from.name))\n      endfor\n    catch\n    endtry\n  endfor\n\n  call call(a:next, [l:locations])\n  return\nendfunction\n\nfunction! go#lsp#DidOpen(fname) abort\n  if get(b:, 'go_lsp_did_open', 0)\n    return\n  endif\n\n  let l:fname = fnamemodify(a:fname, ':p')\n  if !isdirectory(fnamemodify(l:fname, ':h'))\n    return\n  endif\n\n  let l:lsp = s:lspfactory.get()\n\n  if !has_key(l:lsp.notificationQueue, l:fname)\n    let l:lsp.notificationQueue[l:fname] = []\n  endif\n\n  call s:ensureWorkspace(fnamemodify(l:fname, ':h'))\n\n  let l:lsp.fileVersions[l:fname] = getbufvar(l:fname, 'changedtick')\n\n  let l:msg = go#lsp#message#DidOpen(l:fname, join(go#util#GetLines(), \"\\n\") . \"\\n\", l:lsp.fileVersions[l:fname])\n  let l:state = s:newHandlerState('')\n\n  \" TODO(bc): setting a buffer level variable here assumes that a:fname is the\n  \" current buffer. Change to a:fname first before setting it and then change\n  \" back to active buffer.\n  let b:go_lsp_did_open = 1\n\n  return l:lsp.sendMessage(l:msg, l:state)\nendfunction\n\nfunction! go#lsp#DidChange(fname) abort\n  \" DidChange is called even when fname isn't open in a buffer (e.g. via\n  \" go#lsp#Info); don't report the file as open or as having changed when it's\n  \" not actually a buffer.\n  if bufnr(a:fname) == -1\n    return\n  endif\n\n  let l:fname = fnamemodify(a:fname, ':p')\n  if !isdirectory(fnamemodify(l:fname, ':h'))\n    return\n  endif\n\n  call go#lsp#DidOpen(a:fname)\n\n  let l:lsp = s:lspfactory.get()\n\n  let l:version = getbufvar(l:fname, 'changedtick')\n  if has_key(l:lsp.fileVersions, l:fname) && l:lsp.fileVersions[l:fname] == l:version\n    return\n  endif\n  let l:lsp.fileVersions[l:fname] = l:version\n\n  let l:msg = go#lsp#message#DidChange(l:fname, join(go#util#GetLines(), \"\\n\") . \"\\n\", l:lsp.fileVersions[l:fname])\n  let l:state = s:newHandlerState('')\n  return l:lsp.sendMessage(l:msg, l:state)\nendfunction\n\nfunction! go#lsp#DidClose(fname) abort\n  let l:fname = fnamemodify(a:fname, ':p')\n  if !isdirectory(fnamemodify(l:fname, ':h'))\n    return\n  endif\n\n  if !get(b:, 'go_lsp_did_open', 0)\n    return\n  endif\n\n  let l:lsp = s:lspfactory.get()\n  let l:msg = go#lsp#message#DidClose(l:fname)\n  let l:state = s:newHandlerState('')\n  \" TODO(bc): setting a buffer level variable here assumes that a:fname is the\n  \" current buffer. Change to a:fname first before setting it and then change\n  \" back to active buffer.\n  let b:go_lsp_did_open = 0\n\n  return l:lsp.sendMessage(l:msg, l:state)\nendfunction\n\nfunction! go#lsp#Completion(fname, line, col, handler) abort\n  call go#lsp#DidChange(a:fname)\n\n  let l:lsp = s:lspfactory.get()\n  let l:msg = go#lsp#message#Completion(a:fname, a:line, a:col)\n  let l:state = s:newHandlerState('completion')\n  let l:state.handleResult = funcref('s:completionHandler', [function(a:handler, [], l:state)], l:state)\n  let l:state.error = funcref('s:completionErrorHandler', [function(a:handler, [], l:state)], l:state)\n  return l:lsp.sendMessage(l:msg, l:state)\nendfunction\n\nfunction! s:completionHandler(next, msg) abort dict\n  \" gopls returns a CompletionList.\n  let l:matches = []\n  let l:start = -1\n\n  for l:item in a:msg.items\n    let l:start = l:item.textEdit.range.start.character\n\n    let l:match = {'abbr': l:item.label, 'word': l:item.textEdit.newText, 'info': '', 'kind': go#lsp#completionitemkind#Vim(l:item.kind), 'user_data': '', 'icase': go#config#CodeCompletionIcase()}\n    if has_key(l:item, 'detail')\n        let l:match.menu = l:item.detail\n        if go#lsp#completionitemkind#IsFunction(l:item.kind) || go#lsp#completionitemkind#IsMethod(l:item.kind)\n          let l:match.info = printf('%s %s', l:item.label, l:item.detail)\n\n          \" The detail provided by gopls hasn't always provided the the full\n          \" signature including the return value. The label used to be the\n          \" function signature and the detail was the return value. Handle\n          \" that case for backward compatibility. This can be removed in the\n          \" future once it's likely that the majority of users are on a recent\n          \" version of gopls.\n          if l:item.detail !~ '^func'\n            let l:match.info = printf('func %s %s', l:item.label, l:item.detail)\n          endif\n        endif\n    endif\n\n    let l:match.user_data = l:match.info\n    if has_key(l:item, 'documentation')\n      let l:match.info .= \"\\n\\n\" . l:item.documentation\n    endif\n\n    let l:matches = add(l:matches, l:match)\n  endfor\n  let l:args = [l:start, l:matches]\n  call call(a:next, l:args)\nendfunction\n\nfunction! s:completionErrorHandler(next, error) abort dict\n  call call(a:next, [-1, []])\nendfunction\n\n\" go#lsp#SameIDs calls gopls to get the references to the identifier at line\n\" and col in fname. handler should be a dictionary function. handler will be\n\" attached to a dictionary that manages state (statuslines, sets the winid,\n\" etc.). handler should take two arguments: an exit_code and an object with\n\" one property, sameids, whose value is an array of positions, [start line,\n\" start col, end col].\nfunction! go#lsp#SameIDs(showstatus, fname, line, col, handler) abort\n  call go#lsp#DidChange(a:fname)\n\n  let l:lsp = s:lspfactory.get()\n  let l:msg = go#lsp#message#References(a:fname, a:line, a:col)\n\n  if a:showstatus\n    let l:state = s:newHandlerState('same ids')\n  else\n    let l:state = s:newHandlerState('')\n  endif\n\n  let l:state.handleResult = funcref('s:sameIDsHandler', [function(a:handler, [], l:state)], l:state)\n  let l:state.error = funcref('s:noop')\n  return l:lsp.sendMessage(l:msg, l:state)\nendfunction\n\nfunction! s:sameIDsHandler(next, msg) abort dict\n  let l:furi = go#path#ToURI(expand('%:p'))\n\n  let l:result = {\n        \\ 'sameids': [],\n      \\ }\n\n  let l:msg = a:msg\n  if a:msg is v:null\n    let l:msg = []\n  endif\n\n  for l:loc in l:msg\n    if l:loc.uri !=# l:furi\n      continue\n    endif\n\n    let l:line = getline(l:loc.range.start.line + 1)\n    let l:start = go#lsp#lsp#PositionOf(l:line, l:loc.range.start.character)\n    let l:end = go#lsp#lsp#PositionOf(l:line, l:loc.range.end.character)\n    let l:result.sameids = add(l:result.sameids, [l:loc.range.start.line+1, l:start, l:end])\n  endfor\n\n  call call(a:next, [0, l:result])\nendfunction\n\n\" go#lsp#Referrers calls gopls to get the references to the identifier at line\n\" and col in fname. handler should be a dictionary function. handler will be\n\" attached to a dictionary that manages state (statuslines, sets the winid,\n\" etc.). handler should take two arguments: an exit_code and a list of strings\n\" in the form 'file:line:col: message'.\nfunction! go#lsp#Referrers(fname, line, col, handler) abort\n  call go#lsp#DidChange(a:fname)\n\n  let l:lsp = s:lspfactory.get()\n  let l:msg = go#lsp#message#References(a:fname, a:line, a:col)\n\n  let l:state = s:newHandlerState('referrers')\n\n  let l:state.handleResult = funcref('s:handleReferences', [function(a:handler, [], l:state)], l:state)\n  let l:state.error = funcref('s:noop')\n  return l:lsp.sendMessage(l:msg, l:state)\nendfunction\n\nfunction! s:handleReferences(next, msg) abort dict\n  call s:handleLocations(a:next, a:msg)\nendfunction\n\nfunction! s:handleLocations(next, msg) abort\n  let l:result = []\n\n  let l:msg = a:msg\n\n  if l:msg is v:null\n    let l:msg = []\n  endif\n\n  call sort(l:msg, funcref('s:compareLocations'))\n\n  for l:loc in l:msg\n    let l:fname = go#path#FromURI(l:loc.uri)\n    let l:line = l:loc.range.start.line+1\n    let l:content = s:lineinfile(l:fname, l:line)\n    if l:content is -1\n      continue\n    endif\n\n    let l:item = printf('%s:%s:%s: %s', l:fname, l:line, go#lsp#lsp#PositionOf(l:content, l:loc.range.start.character), l:content)\n\n    let l:result = add(l:result, l:item)\n  endfor\n\n  call call(a:next, [0, l:result])\nendfunction\n\n\" go#lsp#Implementations calls gopls to get the implementations to the\n\" identifier at line and col in fname. handler should be a dictionary\n\" function. handler will be attached to a dictionary that manages state\n\" (statuslines, sets the winid, etc.). handler should take two arguments: an\n\" exit_code and a list of strings in the form 'file:line:col: message'.\nfunction! go#lsp#Implements(fname, line, col, handler) abort\n  call go#lsp#DidChange(a:fname)\n\n  let l:lsp = s:lspfactory.get()\n  let l:msg = go#lsp#message#Implementation(a:fname, a:line, a:col)\n\n  let l:state = s:newHandlerState('implements')\n\n  let l:state.handleResult = funcref('s:handleImplements', [function(a:handler, [], l:state)], l:state)\n  let l:state.error = funcref('s:handleImplementsError', [function(a:handler, [], l:state)], l:state)\n  return l:lsp.sendMessage(l:msg, l:state)\nendfunction\n\nfunction! s:handleImplements(next, msg) abort dict\n  call s:handleLocations(a:next, a:msg)\nendfunction\n\nfunction! s:handleImplementsError(next, error) abort dict\n  call call(a:next, [1, [a:error], ''])\nendfunction\n\nfunction! go#lsp#Hover(fname, line, col, handler) abort\n  call go#lsp#DidChange(a:fname)\n\n  let l:lsp = s:lspfactory.get()\n  let l:msg = go#lsp#message#Hover(a:fname, a:line, a:col)\n  let l:state = s:newHandlerState('')\n  let l:diagnosticMsg = ''\n\n  if has_key(l:lsp.diagnostics, a:fname)\n    for l:diagnostic in l:lsp.diagnostics[a:fname]\n      if !s:within(l:diagnostic.range, a:line, a:col)\n        continue\n      endif\n\n      let l:diagnosticMsg = l:diagnostic.message\n      break\n    endfor\n  endif\n  let l:state.handleResult = funcref('s:hoverHandler', [function(a:handler, [], l:state), l:diagnosticMsg], l:state)\n  let l:state.error = funcref('s:hoverError', [function(a:handler, [], l:state), l:diagnosticMsg], l:state)\n  return l:lsp.sendMessage(l:msg, l:state)\nendfunction\n\nfunction! s:hoverHandler(next, diagnostic, msg) abort dict\n  if a:msg is v:null || !has_key(a:msg, 'contents')\n    if len(a:diagnostic) > 0\n      call call(a:next, [a:diagnostic])\n    endif\n    return\n  endif\n\n  try\n    let l:value = json_decode(a:msg.contents.value)\n\n    let l:msg = []\n    if len(a:diagnostic) > 0\n      let l:msg = split(a:diagnostic, \"\\n\")\n      let l:msg = add(l:msg, '')\n    endif\n    let l:signature = split(l:value.signature, \"\\n\")\n    let l:msg = extend(l:msg, l:signature)\n    if go#config#DocBalloon()\n      \" use synopsis instead of fullDocumentation to keep the hover window\n      \" small.\n      let l:doc = l:value.synopsis\n      if len(l:doc) isnot 0\n        let l:msg = extend(l:msg, ['', l:doc])\n      endif\n    endif\n\n    call call(a:next, [l:msg])\n  catch\n    \" TODO(bc): log the message and/or show an error message.\n  endtry\nendfunction\n\nfunction! s:hoverError(next, diagnostic, msg) abort dict\n  try\n    if len(a:diagnostic) > 0\n      let l:msg = split(a:diagnostic, \"\\n\")\n      call call(a:next, [l:msg])\n    endif\n  catch\n  endtry\n\n  return\nendfunction\n\nfunction! go#lsp#Doc() abort\n  let l:fname = expand('%:p')\n  let [l:line, l:col] = go#lsp#lsp#Position()\n\n  call go#lsp#DidChange(l:fname)\n\n  let l:lsp = s:lspfactory.get()\n  let l:msg = go#lsp#message#Hover(l:fname, l:line, l:col)\n  let l:state = s:newHandlerState('doc')\n  let l:resultHandler = go#promise#New(function('s:docFromHoverResult', [], l:state), 10000, '')\n  let l:state.handleResult = l:resultHandler.wrapper\n  let l:state.error = l:resultHandler.wrapper\n  call l:lsp.sendMessage(l:msg, l:state)\n  return l:resultHandler.await()\nendfunction\n\nfunction! s:docFromHoverResult(msg) abort dict\n  if type(a:msg) is type('')\n    return [a:msg, 1]\n  endif\n\n  if a:msg is v:null || !has_key(a:msg, 'contents')\n    return ['Undocumented', 0]\n  endif\n\n  let l:value = json_decode(a:msg.contents.value)\n  let l:doc = l:value.fullDocumentation\n  if len(l:doc) is 0\n    let l:doc = 'Undocumented'\n  endif\n  let l:content = printf(\"%s\\n\\n%s\", l:value.signature, l:doc)\n  return [l:content, 0]\nendfunction\n\nfunction! go#lsp#DocLink() abort\n  let l:fname = expand('%:p')\n  let [l:line, l:col] = go#lsp#lsp#Position()\n\n  call go#lsp#DidChange(l:fname)\n\n  let l:lsp = s:lspfactory.get()\n  let l:msg = go#lsp#message#Hover(l:fname, l:line, l:col)\n  let l:state = s:newHandlerState('doc url')\n  let l:resultHandler = go#promise#New(function('s:docLinkFromHoverResult', [], l:state), 10000, '')\n  let l:state.handleResult = l:resultHandler.wrapper\n  let l:state.error = l:resultHandler.wrapper\n  call l:lsp.sendMessage(l:msg, l:state)\n  return l:resultHandler.await()\nendfunction\n\nfunction! s:docLinkFromHoverResult(msg) abort dict\n  if type(a:msg) is type('')\n    return [a:msg, 1]\n  endif\n\n  if a:msg is v:null || !has_key(a:msg, 'contents')\n    return ['', 0]\n  endif\n  let l:doc = json_decode(a:msg.contents.value)\n\n  \" for backward compatibility with older gopls\n  if has_key(l:doc, 'link')\n    let l:link = l:doc.link\n    return [l:doc.link, 0]\n  endif\n\n  if !has_key(l:doc, 'linkPath') || empty(l:doc.linkPath)\n    return ['', 0]\n  endif\n  let l:link = l:doc.linkPath . \"#\" . l:doc.linkAnchor\n  return [l:link, 0]\nendfunction\n\nfunction! go#lsp#Info(showstatus)\n  let l:fname = expand('%:p')\n  let [l:line, l:col] = go#lsp#lsp#Position()\n\n  call go#lsp#DidChange(l:fname)\n\n  let l:lsp = s:lspfactory.get()\n\n  if a:showstatus\n    let l:state = s:newHandlerState('info')\n  else\n    let l:state = s:newHandlerState('')\n  endif\n\n  let l:state.handleResult = funcref('s:infoDefinitionHandler', [function('s:info', [1], l:state), a:showstatus], l:state)\n  let l:state.error = funcref('s:noop')\n  let l:msg = go#lsp#message#Definition(l:fname, l:line, l:col)\n  return l:lsp.sendMessage(l:msg, l:state)\nendfunction\n\nfunction! go#lsp#GetInfo()\n  let l:fname = expand('%:p')\n  let [l:line, l:col] = go#lsp#lsp#Position()\n\n  call go#lsp#DidChange(l:fname)\n\n  let l:lsp = s:lspfactory.get()\n\n  let l:state = s:newHandlerState('')\n\n  let l:info = go#promise#New(function('s:info', [0], l:state), 10000, '')\n\n  let l:state.handleResult = funcref('s:infoDefinitionHandler', [l:info.wrapper, 0], l:state)\n  let l:state.error = funcref('s:noop')\n  let l:msg = go#lsp#message#Definition(l:fname, l:line, l:col)\n  call l:lsp.sendMessage(l:msg, l:state)\n  return l:info.await()\nendfunction\n\nfunction! s:infoDefinitionHandler(next, showstatus, msg) abort dict\n  \" gopls returns a []Location; just take the first one.\n  if a:msg is v:null || len(a:msg) == 0\n    return\n  endif\n\n  let l:msg = a:msg[0]\n\n  let l:fname = go#path#FromURI(l:msg.uri)\n  let l:line = l:msg.range.start.line\n  let l:col = l:msg.range.start.character\n\n  let l:lsp = s:lspfactory.get()\n  let l:msg = go#lsp#message#Hover(l:fname, l:line, l:col)\n\n  if a:showstatus\n    let l:state = s:newHandlerState('info')\n  else\n    let l:state = s:newHandlerState('')\n  endif\n\n  let l:state.handleResult = a:next\n  let l:state.error = funcref('s:noop')\n  return l:lsp.sendMessage(l:msg, l:state)\nendfunction\n\nfunction! s:info(show, msg) abort dict\n  if a:msg is v:null || !has_key(a:msg, 'contents')\n    return\n  endif\n\n  let l:value = json_decode(a:msg.contents.value)\n  let l:content = [l:value.singleLine]\n  let l:content = s:infoFromHoverContent(l:content)\n\n  if a:show\n    call go#util#ShowInfo(l:content)\n  endif\n\n  return l:content\nendfunction\n\nfunction! s:infoFromHoverContent(content) abort\n  if len(a:content) < 1\n    return ''\n  endif\n\n  let l:content = a:content[0]\n\n  \" strip off the method set and fields of structs and interfaces.\n  if l:content =~# '^\\(type \\)\\?[^ ]\\+ \\(struct\\|interface\\)'\n    let l:content = substitute(l:content, '{.*', '', '')\n  endif\n\n  return l:content\nendfunction\n\nfunction! go#lsp#AddWorkspaceDirectory(...) abort\n  if a:0 == 0\n    return\n  endif\n\n  call go#lsp#CleanWorkspaces()\n\n  let l:workspaces = []\n  for l:dir in a:000\n    let l:dir = fnamemodify(l:dir, ':p')\n    if len(l:dir) > 1 && l:dir[-1:] == '/'\n      let l:dir = l:dir[:-2]\n    endif\n    if !isdirectory(l:dir)\n      continue\n    endif\n\n    let l:workspaces = add(l:workspaces, l:dir)\n  endfor\n\n  let l:lsp = s:lspfactory.get()\n  let l:state = s:newHandlerState('')\n  let l:lsp.workspaceDirectories = s:dedup(extend(l:lsp.workspaceDirectories, l:workspaces))\n  let l:msg = go#lsp#message#ChangeWorkspaceFolders(l:workspaces, [])\n  call l:lsp.sendMessage(l:msg, l:state)\n\n  return 0\nendfunction\n\nfunction! go#lsp#CleanWorkspaces() abort\n  let l:workspaces = []\n\n  let l:lsp = s:lspfactory.get()\n\n  let l:i = 0\n  let l:missing = []\n  for l:dir in l:lsp.workspaceDirectories\n    if !isdirectory(l:dir)\n      let l:missing = add(l:missing, l:dir)\n      call remove(l:lsp.workspaceDirectories, l:i)\n      continue\n    endif\n    let l:i += 1\n  endfor\n\n  if len(l:missing) == 0\n    return 0\n  endif\n\n  let l:state = s:newHandlerState('')\n  let l:msg = go#lsp#message#ChangeWorkspaceFolders([], s:dedup(l:missing))\n  call l:lsp.sendMessage(l:msg, l:state)\n\n  return 0\nendfunction\n\n\" go#lsp#ResetWorkspaceDiretories removes and then re-adds all workspace\n\" folders to cause gopls to send configuration requests for all of them again.\n\" This is useful, for instance, when build tags have been added and gopls\n\" needs to use them.\nfunction! go#lsp#ResetWorkspaceDirectories() abort\n  call go#lsp#CleanWorkspaces()\n\n  let l:lsp = s:lspfactory.get()\n\n  let l:state = s:newHandlerState('')\n  let l:msg = go#lsp#message#ChangeWorkspaceFolders(s:dedup(l:lsp.workspaceDirectories), s:dedup(l:lsp.workspaceDirectories))\n  call l:lsp.sendMessage(l:msg, l:state)\n\n  return 0\nendfunction\n\nfunction! go#lsp#DebugBrowser() abort\n  let l:lsp = s:lspfactory.get()\n  let l:port = get(l:lsp, 'debugport', 0)\n  if !l:port\n    call go#util#EchoError(\"gopls was not started with debugging enabled. See :help g:go_debug.\")\n    return\n  endif\n\n  call go#util#OpenBrowser(printf('http://localhost:%d', l:port))\nendfunction\n\nfunction! go#lsp#Exit() abort\n  call s:exit(0)\nendfunction\n\nfunction! go#lsp#Restart() abort\n  call s:exit(1)\nendfunction\n\nfunction! s:exit(restart) abort\n  if !go#util#has_job() || len(s:lspfactory) == 0 || !has_key(s:lspfactory, 'current')\n    return\n  endif\n\n  let l:lsp = s:lspfactory.get()\n\n  \" reset the factory so that future requests don't use the same instance of\n  \" gopls.\n  call s:lspfactory.reset()\n\n  let l:lsp.restarting = a:restart\n\n  let l:state = s:newHandlerState('exit')\n\n  let l:msg = go#lsp#message#Shutdown()\n  let l:retval = l:lsp.sendMessage(l:msg, l:state)\n\n  let l:msg = go#lsp#message#Exit()\n  let l:retval = l:lsp.sendMessage(l:msg, l:state)\n\n  return l:retval\nendfunction\n\nlet s:log = []\nlet s:logtimer = 0\nfunction! s:debugasync(timer) abort\n  let s:logtimer = 0\n\n  if !go#util#HasDebug('lsp')\n    let s:log = []\n    return\n  endif\n\n  \" set the timer to try again if Vim is in a state where we don't want to\n  \" change the window.\n  if exists('*state')\n    let l:state = state('a')\n  else\n    let l:state = mode(1)\n    if !(l:state == 'ic' || l:state == 'Rc' || l:state == 'Rvc')\n      let l:state = ''\n    endif\n  endif\n  let l:mode = mode(1)\n  if len(l:state) > 0 || l:mode[0] == 'v' || l:mode[0] == 'V' || l:mode[0] == 's' || l:mode =~ 'CTRL-V'\n    let s:logtimer = timer_start(go#config#DebugLogDelay(), function('s:debugasync', []))\n    return\n  endif\n\n  try\n    let l:winid = win_getid()\n\n    let l:name = '__GOLSP_LOG__'\n    let l:log_winid = bufwinid(l:name)\n    if l:log_winid == -1\n      silent keepalt botright 10new\n      silent file `='__GOLSP_LOG__'`\n      setlocal buftype=nofile bufhidden=wipe nomodified nobuflisted noswapfile nowrap nonumber nocursorline\n      setlocal filetype=golsplog\n      setlocal fileencoding=utf-8\n      call win_gotoid(l:winid)\n    endif\n\n    let l:logwinid = bufwinid(l:name)\n\n    try\n      call setbufvar(l:name, '&modifiable', 1)\n      for [l:event, l:data] in s:log\n        call remove(s:log, 0)\n        if getbufline(l:name, 1)[0] == ''\n          call setbufline(l:name, '$', printf('===== %s =====', l:event))\n        else\n          call appendbufline(l:name, '$', printf('===== %s =====', l:event))\n        endif\n        call appendbufline(l:name, '$', split(l:data, \"\\r\\n\"))\n      endfor\n\n      \" Move the window's cursor position without switching to the window\n      call win_execute(l:logwinid, 'normal! G')\n      call setbufvar(l:name, '&modifiable', 0)\n    finally\n    endtry\n  catch\n    call go#util#EchoError(printf('at %s: %s', v:throwpoint, v:exception))\n  finally\n    \" retry when there's an exception. This can happen when trying to do\n    \" completion, because the window can not be changed while completion is in\n    \" progress.\n    if len(s:log) != 0\n      let s:logtimer = timer_start(go#config#DebugLogDelay(), function('s:debugasync', []))\n    endif\n  endtry\nendfunction\n\nfunction! s:debug(event, data) abort\n  let l:shouldStart = s:logtimer is 0\n  let s:log = add(s:log, [a:event, a:data])\n\n  if l:shouldStart\n    let s:logtimer = timer_start(go#config#DebugLogDelay(), function('s:debugasync', []))\n  endif\nendfunction\n\nfunction! s:compareLocations(left, right) abort\n  if a:left.uri < a:right.uri\n    return -1\n  endif\n\n  if a:left.uri == a:right.uri && a:left.range.start.line < a:right.range.start.line\n    return -1\n  endif\n\n  if a:left.uri == a:right.uri && a:left.range.start.line == a:right.range.start.line && a:left.range.start.character < a:right.range.start.character\n    return -1\n  endif\n\n  if a:left.uri == a:right.uri && a:left.range.start.line == a:right.range.start.line && a:left.range.start.character == a:right.range.start.character\n    return 0\n  endif\n\n  return 1\nendfunction\n\nfunction! go#lsp#Diagnostics(...) abort\n  if a:0 == 0\n    return []\n  endif\n\n  let l:dirsToPackages = {}\n\n  let l:lsp = s:lspfactory.get()\n\n  let l:diagnostics = []\n  for [l:key, l:val] in items(l:lsp.diagnostics)\n    let l:dir = fnamemodify(l:key, ':h')\n\n    if !has_key(l:dirsToPackages, l:dir)\n      let l:pkg = go#package#FromPath(l:dir)\n      let l:dirsToPackages[l:dir] = l:pkg\n    else\n      let l:pkg = l:dirsToPackages[l:dir]\n    endif\n\n    if type(l:pkg) == type(0)\n      continue\n    endif\n\n    for l:arg in a:000\n      if l:arg == l:pkg || l:arg == 'all'\n        let l:diagnostics = extend(l:diagnostics, map(l:val, 'v:val[\"error\"]'))\n      endif\n    endfor\n  endfor\n\n  return sort(l:diagnostics)\nendfunction\n\nfunction! go#lsp#AnalyzeFile(fname) abort\n  let l:fname = fnamemodify(a:fname, ':p')\n  if !isdirectory(fnamemodify(l:fname, ':h'))\n    return []\n  endif\n\n  let l:lsp = s:lspfactory.get()\n\n  let l:lastdiagnostics = get(l:lsp.diagnostics, l:fname, [])\n\n  let l:version = get(l:lsp.fileVersions, a:fname, 0)\n  if l:version == getbufvar(a:fname, 'changedtick')\n    return map(l:lastdiagnostics, 'v:val[\"error\"]')\n  endif\n\n  call go#lsp#DidChange(a:fname)\n\n  let l:diagnostics = go#promise#New(function('s:setDiagnostics', []), 10000, l:lastdiagnostics)\n  let l:lsp.notificationQueue[l:fname] = add(get(l:lsp.notificationQueue, l:fname, []), l:diagnostics.wrapper)\n  return l:diagnostics.await()\nendfunction\n\nfunction! s:setDiagnostics(...) abort\n  return map(a:000, 'v:val[\"error\"]')\nendfunction\n\n\" s:processDiagnostic converts a diagnostic from LSP into useful values for\n\" Vim. It returns the a value with the original message, the diagnostic range\n\" as expressed by LSP, an error string, and the Vim match position described\n\" in the diagnostic. The match position will be an empty list when bufname is\n\" not a valid name for the current buffer.\nfunction! s:processDiagnostic(diagnostic, bufname, fname) abort\n  let l:range = a:diagnostic.range\n\n  let l:diagnostic = {\n        \\ \"message\": a:diagnostic.message,\n        \\ \"range\": {\n          \\ \"start\": {\n            \\ \"line\": l:range.start.line,\n            \\ \"character\": l:range.start.character,\n          \\ },\n          \\ \"end\": {\n            \\ \"line\": l:range.end.line,\n            \\ \"character\": l:range.end.character,\n          \\ },\n        \\ },\n      \\ }\n\n  let l:line = l:range.start.line + 1\n  let l:endline = l:range.end.line + 1\n\n  let l:buflines = getbufline(a:bufname, l:line)\n  let l:col = ''\n  if len(l:buflines) > 0\n    let l:col = go#lsp#lsp#PositionOf(l:buflines[0], l:range.start.character)\n  endif\n\n  let l:severity = go#lsp#lsp#SeverityToErrorType(a:diagnostic.severity)\n  let l:diagnostic.error = printf('%s:%s:%s:%s: %s', a:fname, l:line, l:col, l:severity, l:diagnostic.message)\n\n  if !(a:diagnostic.severity == 1 || a:diagnostic.severity == 2)\n    return [l:diagnostic, []]\n  endif\n\n  \" return when the diagnostic is not for the current buffer.\n  if bufnr(a:bufname) != bufnr('')\n    return [l:diagnostic, []]\n  end\n\n  \" don't bother trying to highlight errors or warnings that span\n  \" the whole file (e.g when there's missing package documentation).\n  if l:line == 1 && (l:endline) == line('$')\n    return [l:diagnostic, []]\n  endif\n\n  if len(l:buflines) == 0\n    return [l:diagnostic, []]\n  endif\n\n  let l:buflines = getbufline(a:bufname, l:endline)\n  if len(l:buflines) > 0\n    let l:endcol = go#lsp#lsp#PositionOf(l:buflines[0], l:range.end.character)\n  else\n    return [l:diagnostic, []]\n  endif\n\n  \" the length of the match is the number of bytes between the start of\n  \" the match and the end of the match.\n  let l:matchLength = line2byte(l:endline) + l:endcol - (line2byte(l:line) + l:col)\n  let l:pos = [l:line, l:col, l:matchLength]\n\n  return [l:diagnostic, l:pos]\nendfunction\n\nfunction! s:highlightMatches(errorMatches, warningMatches) abort\n  \" set buffer variables for errors and warnings to zero values\n  let b:go_diagnostic_matches = {'errors': [], 'warnings': []}\n\n  if hlexists('goDiagnosticError')\n    \" clear the old matches just before adding the new ones to keep flicker\n    \" to a minimum and clear before checking the level so that if the user\n    \" changed the level since the last highlighting, the highlighting will be\n    \" be properly cleared.\n    call go#util#ClearHighlights('goDiagnosticError')\n    if go#config#DiagnosticsLevel() >= 2\n      let b:go_diagnostic_matches.errors = copy(a:errorMatches)\n      if go#config#HighlightDiagnosticErrors()\n        call go#util#HighlightPositions('goDiagnosticError', a:errorMatches)\n      endif\n    endif\n  endif\n\n  if hlexists('goDiagnosticWarning')\n    \" clear the old matches just before adding the new ones to keep flicker\n    \" to a minimum and clear before checking the level so that if the user\n    \" changed the level since the last highlighting, the highlighting will be\n    \" be properly cleared.\n    call go#util#ClearHighlights('goDiagnosticWarning')\n    if go#config#DiagnosticsLevel() >= 2\n      let b:go_diagnostic_matches.warnings = copy(a:warningMatches)\n      if go#config#HighlightDiagnosticWarnings()\n        call go#util#HighlightPositions('goDiagnosticWarning', a:warningMatches)\n      endif\n    endif\n  endif\n\n  \" re-apply matches at the time the buffer is displayed in a new window or\n  \" redisplayed in an existing window: e.g. :edit,\n  augroup vim-go-diagnostics\n    autocmd! * <buffer>\n    autocmd BufDelete <buffer> autocmd! vim-go-diagnostics * <buffer=abuf>\n    if has('textprop')\n      autocmd BufReadPost <buffer> nested call s:highlightMatches(b:go_diagnostic_matches.errors, b:go_diagnostic_matches.warnings)\n    else\n      autocmd BufWinEnter <buffer> nested call s:highlightMatches(b:go_diagnostic_matches.errors, b:go_diagnostic_matches.warnings)\n    endif\n  augroup end\nendfunction\n\n\" ClearDiagnosticHighlights removes all goDiagnosticError and\n\" goDiagnosticWarning matches.\nfunction! go#lsp#ClearDiagnosticHighlights() abort\n  call go#util#ClearHighlights('goDiagnosticError')\n  call go#util#ClearHighlights('goDiagnosticWarning')\nendfunction\n\n\" Format formats the current buffer.\nfunction! go#lsp#Format() abort\n  let l:fname = expand('%:p')\n  \" send the current file so that TextEdits will be relative to the current\n  \" state of the buffer.\n  call go#lsp#DidChange(l:fname)\n\n  let l:lsp = s:lspfactory.get()\n\n  let l:state = s:newHandlerState('')\n  let l:handleFormat = go#promise#New(function('s:handleFormat', [], l:state), 10000, '')\n  let l:state.handleResult = l:handleFormat.wrapper\n  let l:state.error = l:handleFormat.wrapper\n  let l:state.handleError = function('s:handleFormatError', [l:fname], l:state)\n  let l:msg = go#lsp#message#Format(l:fname)\n  call l:lsp.sendMessage(l:msg, l:state)\n\n  call go#fmt#CleanErrors()\n\n  \" await the result to avoid any race conditions among autocmds (e.g.\n  \" BufWritePre and BufWritePost)\n  call l:handleFormat.await()\nendfunction\n\n\" Imports executes the source.organizeImports code action for the current\n\" buffer.\nfunction! go#lsp#Imports() abort\n  let l:fname = expand('%:p')\n  \" send the current file so that TextEdits will be relative to the current\n  \" state of the buffer.\n  call go#lsp#DidChange(l:fname)\n\n  let l:lsp = s:lspfactory.get()\n\n  let l:state = s:newHandlerState('')\n  let l:handler = go#promise#New(function('s:handleCodeAction', ['source.organizeImports', '', ''], l:state), 10000, '')\n  let l:state.handleResult = l:handler.wrapper\n  let l:state.error = l:handler.wrapper\n  let l:state.handleError = function('s:handleCodeActionError', [l:fname], l:state)\n  let l:msg = go#lsp#message#CodeActionImports(l:fname)\n  call l:lsp.sendMessage(l:msg, l:state)\n\n  \" await the result to avoid any race conditions among autocmds (e.g.\n  \" BufWritePre and BufWritePost)\n  call l:handler.await()\nendfunction\n\n\" FillStruct executes the refactor.rewrite code action for the current buffer\n\" and configures the handler to only apply the fillstruct command for the\n\" current location.\nfunction! go#lsp#FillStruct() abort\n  let l:fname = expand('%:p')\n  \" send the current file so that TextEdits will be relative to the current\n  \" state of the buffer.\n  call go#lsp#DidChange(l:fname)\n\n  let l:lsp = s:lspfactory.get()\n\n  let l:state = s:newHandlerState('')\n  let l:handler = go#promise#New(function('s:handleCodeAction', ['refactor.rewrite.fillStruct', 'apply_fix', 'fillstruct'], l:state), 10000, '')\n  let l:state.handleResult = l:handler.wrapper\n  let l:state.error = l:handler.wrapper\n  let l:state.handleError = function('s:handleCodeActionError', [l:fname], l:state)\n\n  let [l:line, l:col] = go#lsp#lsp#Position()\n  let l:msg = go#lsp#message#CodeActionFillStruct(l:fname, l:line, l:col)\n  call l:lsp.sendMessage(l:msg, l:state)\n\n  \" await the result to avoid any race conditions among autocmds (e.g.\n  \" BufWritePre and BufWritePost)\n  call l:handler.await()\nendfunction\n\n\" Extract executes the refactor.extract code action for the current buffer\n\" and configures the handler to only apply the fillstruct command for the\n\" current location.\nfunction! go#lsp#Extract(line1, line2) abort\n  let l:fname = expand('%:p')\n  \" send the current file so that TextEdits will be relative to the current\n  \" state of the buffer.\n  call go#lsp#DidChange(l:fname)\n\n  let l:lsp = s:lspfactory.get()\n\n  let l:state = s:newHandlerState('')\n  let l:handler = go#promise#New(function('s:handleCodeAction', ['refactor.extract.function', 'apply_fix', 'extract_function'], l:state), 10000, '')\n  let l:state.handleResult = l:handler.wrapper\n  let l:state.error = l:handler.wrapper\n  let l:state.handleError = function('s:handleCodeActionError', [l:fname], l:state)\n\n  if a:line1 == -1\n    let [l:startline, l:startcol] = go#lsp#lsp#Position(line('.'), 1)\n  else\n    let [l:startline, l:startcol] = go#lsp#lsp#Position(a:line1, 1)\n  endif\n  if a:line2 == -1\n    let [l:endline, l:endcol] = go#lsp#lsp#Position(line('.'), col('$'))\n  else\n    let [l:endline, l:endcol] = go#lsp#lsp#Position(a:line2, col([a:line2, '$']))\n  endif\n\n  let l:msg = go#lsp#message#CodeActionRefactorExtract(l:fname, l:startline, l:startcol, l:endline, l:endcol)\n  call l:lsp.sendMessage(l:msg, l:state)\n\n  \" await the result to avoid any race conditions among autocmds (e.g.\n  \" BufWritePre and BufWritePost)\n  call l:handler.await()\nendfunction\n\nfunction! go#lsp#Rename(newName) abort\n  let l:fname = expand('%:p')\n  let [l:line, l:col] = go#lsp#lsp#Position()\n\n  call go#lsp#DidChange(l:fname)\n\n  let l:lsp = s:lspfactory.get()\n  let l:msg = go#lsp#message#PrepareRename(l:fname, l:line, l:col)\n  let l:state = s:newHandlerState('rename')\n  let l:resultHandler = go#promise#New(function('s:rename', [l:fname, l:line, l:col, a:newName], l:state), 10000, '')\n\n  let l:state.handleResult = l:resultHandler.wrapper\n  let l:state.error = l:resultHandler.wrapper\n  let l:state.handleError = function('s:handleRenameError', [], l:state)\n  call l:lsp.sendMessage(l:msg, l:state)\n\n  return l:resultHandler.await()\nendfunction\n\nfunction! go#lsp#ModReload(...) abort\n  let l:gomod = 'go.mod'\n  if a:0 is 0\n    let l:modroot = go#util#ModuleRoot()\n    if l:modroot is -1\n      call go#util#EchoError('go module not found')\n      return\n    endif\n    let l:gomod = printf('%s/%s', l:modroot, 'go.mod')\n  else\n    let l:gomod = a:1\n  endif\n\n  if l:gomod !~ 'go.mod$'\n    let l:gomod = printf('%s/%s', l:gomod, 'go.mod')\n  endif\n  let l:gomod = fnamemodify(l:gomod, ':p')\n\n  if !filereadable(l:gomod)\n    call go#util#EchoError('go.mod does not exist')\n    return\n  endif\n\n  let l:lsp = s:lspfactory.get()\n  let l:msg = go#lsp#message#DidChangeWatchedFile(l:gomod, 'Changed')\n  let l:state = s:newHandlerState('')\n  return l:lsp.sendMessage(l:msg, l:state)\nendfunction\n\nfunction! s:rename(fname, line, col, newName, msg) abort dict\n  if type(a:msg) is type('')\n    call self.handleError(a:msg)\n    return\n  endif\n\n  if a:msg is v:null\n    call go#util#EchoWarning('cannot rename the identifier at the requested position')\n    return\n  endif\n\n  call go#lsp#DidChange(a:fname)\n\n  let l:lsp = s:lspfactory.get()\n  let l:msg = go#lsp#message#Rename(a:fname, a:line, a:col, a:newName)\n  let l:state = s:newHandlerState('rename')\n  let l:resultHandler = go#promise#New(function('s:handleRename', [], l:state), 10000, '')\n\n  let l:state.handleResult = l:resultHandler.wrapper\n  let l:state.error = l:resultHandler.wrapper\n  let l:state.handleError = function('s:handleRenameError', [], l:state)\n  call l:lsp.sendMessage(l:msg, l:state)\n\n  return l:resultHandler.await()\nendfunction\n\nfunction! s:handleRename(msg) abort dict\n  if type(a:msg) is type('')\n    call self.handleError(a:msg)\n    return\n  endif\n\n  if a:msg is v:null\n    return\n  endif\n  call s:applyDocumentChanges(a:msg.documentChanges)\nendfunction\n\nfunction! s:executeCommand(cmd, args) abort\n  let l:lsp = s:lspfactory.get()\n\n  let l:state = s:newHandlerState('')\n\n  let l:msg = go#lsp#message#ExecuteCommand(a:cmd, a:args)\n  call l:lsp.sendMessage(l:msg, l:state)\nendfunction\n\nfunction! s:handleFormat(msg) abort dict\n  call go#fmt#CleanErrors()\n\n  if type(a:msg) is type('')\n    call self.handleError(a:msg)\n    return\n  endif\n  call s:applyTextEdits(bufnr(''), a:msg)\nendfunction\n\nfunction! s:handleCodeAction(kind, cmd, fix, msg) abort dict\n  if type(a:msg) is type('')\n    call self.handleError(a:msg)\n    return\n  endif\n\n  if a:msg is v:null\n    return\n  endif\n\n  for l:item in a:msg\n    \" TODO(bc): always pass in exactly the right kind and remove the fix\n    \" paramter entirely after\n    \" https://github.com/golang/go/issues/68791 is merged and released.\n    if get(l:item, 'kind', '') is a:kind || l:item.kind is printf('%s.%s', a:kind, a:fix)\n      if has_key(l:item, 'disabled') && get(l:item.disabled, 'reason', '') isnot ''\n        call go#util#EchoWarning(printf('code action is disabled: %s', l:item.disabled.reason))\n        continue\n      endif\n\n      if has_key(l:item, 'command')\n        if has_key(l:item.command, 'command') &&\n              \\ (l:item.command.command is a:cmd ||\n                \\ (l:item.command.command is printf('gopls.%s', a:cmd) &&\n                  \\ (a:fix is '' ||\n                    \\ (has_key(l:item.command, 'arguments') &&\n                    \\ type(l:item.command.arguments) is type([]) &&\n                    \\ len(l:item.command.arguments) > 0 &&\n                    \\ type(l:item.command.arguments[0]) is type({}) &&\n                    \\ has_key(l:item.command.arguments[0], 'Fix') &&\n                    \\ a:fix == l:item.command.arguments[0].Fix))))\n          call s:executeCommand(l:item.command.command, l:item.command.arguments)\n          continue\n        endif\n      endif\n\n      if !has_key(l:item, 'edit')\n        continue\n      endif\n\n      if !has_key(l:item.edit, 'documentChanges')\n        continue\n      endif\n      call s:applyDocumentChanges(l:item.edit.documentChanges)\n    endif\n  endfor\nendfunction\n\nfunction s:applyDocumentChanges(changes)\n  let l:bufnr = bufnr('')\n\n  for l:change in a:changes\n    if !has_key(l:change, 'edits')\n      continue\n    endif\n    let l:fname = go#path#FromURI(l:change.textDocument.uri)\n\n    \" get the buffer name relative to the current directory, because\n    \" Vim says that a buffer name can't be an absolute path.\n    let l:bufname = fnamemodify(l:fname, ':.')\n\n    let l:bufadded = 0\n    let l:bufloaded = 0\n\n    let l:editbufnr = bufnr(l:bufname)\n    if l:editbufnr != bufnr('')\n      \" make sure the buffer is listed and loaded before applying text edits\n      if !bufexists(l:bufname)\n        call bufadd(l:bufname)\n        let l:bufadded = 1\n      endif\n\n      if !bufloaded(l:bufname)\n        call bufload(l:bufname)\n        let l:bufloaded = 1\n      endif\n\n      let l:editbufnr = bufnr(l:bufname)\n      if l:editbufnr == -1\n        call go#util#EchoWarning(printf('could not apply changes to %s', l:fname))\n        continue\n      endif\n\n       \" TODO(bc): do not edit the buffer when vim-go drops support for Vim\n       \" 8.0. Instead, use the functions to modify a buffer (e.g.\n       \" appendbufline, getbufline, deletebufline).\n       execute printf('keepalt keepjumps buffer! %d', l:editbufnr)\n    endif\n    call s:applyTextEdits(l:editbufnr, l:change.edits)\n\n    \" TODO(bc): save the buffer?\n    \" TODO(bc): unload and/or delete a buffer that was loaded or added,\n    \" respectively?\n  endfor\n  if bufnr('') != l:bufnr\n    execute printf('keepalt keepjumps buffer! %d', l:bufnr)\n  endif\nendfunction\n\n\" s:applyTextEdit applies the list of WorkspaceEdit values in msg.\nfunction s:applyTextEdits(bufnr, msg) abort\n  if a:msg is v:null\n    return\n  endif\n\n  \" TODO(bc): start using the functions to modify a buffer (e.g. appendbufline,\n  \" deletebufline, etc) instead of operating on the current buffer when vim-go\n  \" drops support from Vim 8.0.\n\n  \" process the TextEdit list in reverse order, because the positions are\n  \" based on the current line numbers; processing in forward order would\n  \" require keeping track of how the proper position of each TextEdit would be\n  \" affected by all the TextEdits that came before.\n  call reverse(sort(a:msg, function('s:textEditLess')))\n  for l:msg in a:msg\n    let l:startline = l:msg.range.start.line+1\n    let l:endline = l:msg.range.end.line+1\n    let l:text = l:msg.newText\n\n    \" handle the deletion of whole lines\n    if len(l:text) == 0 && l:msg.range.start.character == 0 && l:msg.range.end.character == 0 && l:startline < l:endline\n      call s:deleteline(l:startline, l:endline-1)\n      continue\n    endif\n\n    \" Assume that l:startcontent will be an empty string. When the replacement\n    \" is not at the beginning of the line, then l:startcontent must be what\n    \" comes before the start position on the start line.\n    let l:startcontent = ''\n    if l:msg.range.start.character > 0\n      let l:startcontent = getline(l:startline)\n      let l:preSliceEnd = go#lsp#lsp#PositionOf(l:startcontent, l:msg.range.start.character-1)\n      let l:startcontent = strcharpart(l:startcontent, 0, l:preSliceEnd) \"l:startcontent[:l:preSliceEnd]\n    endif\n\n    let l:endcontent = getline(l:endline)\n    let l:postSliceStart = 0\n    if l:msg.range.end.character > 0\n      let l:postSliceStart = go#lsp#lsp#PositionOf(l:endcontent, l:msg.range.end.character-1)\n      let l:endcontent = strcharpart(l:endcontent, l:postSliceStart) \"l:endcontent[(l:postSliceStart):]\n    endif\n\n    \" There isn't an easy way to replace the text in a byte or character\n    \" range, so append to l:text any text on l:endline starting from\n    \" l:postSliceStart and prepend to l:text any text on l:startline prior to\n    \" l:preSliceEnd, and finally replace the lines with a delete followed by\n    \" and append.\n    let l:text = printf('%s%s%s', l:startcontent, l:text, l:endcontent)\n\n    \" TODO(bc): deal with the undo file\n    \" TODO(bc): deal with folds\n\n    \" TODO(bc): can we use appendbufline instead of deleting and appending?\n    call s:deleteline(l:startline, l:endline)\n    for l:line in split(l:text, \"\\n\", 1)\n      call append(l:startline-1, l:line)\n      let l:startline += 1\n    endfor\n  endfor\n\n  call go#lsp#DidChange(expand('%:p'))\n  return\nendfunction\n\nfunction! s:handleFormatError(filename, msg) abort dict\n  if go#config#FmtFailSilently()\n    return\n  endif\n\n  let l:errors = split(a:msg, '\\n')\n  let l:errors = map(l:errors, printf('substitute(v:val, ''^'', ''%s:'', '''')', a:filename))\n  let l:errors = join(l:errors, \"\\n\")\n  call go#fmt#ShowErrors(l:errors)\nendfunction\n\nfunction! s:handleCodeActionError(filename, msg) abort dict\n  call go#util#EchoError(a:msg)\nendfunction\n\nfunction! s:handleRenameError(msg) abort dict\n  call go#util#EchoError(a:msg)\nendfunction\n\nfunction! s:textEditLess(left, right) abort\n  \" TextEdits in a TextEdit[] never overlap and Vim's sort() is stable.\n  if a:left.range.start.line < a:right.range.start.line\n    return -1\n  endif\n\n  if a:left.range.start.line > a:right.range.start.line\n    return 1\n  endif\n\n  if a:left.range.start.line == a:right.range.start.line\n    if a:left.range.start.character < a:right.range.start.character\n      return -1\n    endif\n\n    if a:left.range.start.character > a:right.range.start.character\n      return 1\n    endif\n  endif\n\n  \" return 0, because a:left and a:right refer to the same position.\n  return 0\nendfunction\n\nfunction! s:deleteline(start, end) abort\n  if exists('*deletebufline')\n    call deletebufline('', a:start, a:end)\n  else\n    call execute(printf('%d,%d d_', a:start, a:end))\n  endif\nendfunction\n\nfunction! s:ensureWorkspace(dir)\n  let l:modroot = go#util#ModuleRoot(a:dir)\n  if l:modroot is -1 || l:modroot is ''\n    return\n  endif\n\n\n  let l:lsp = s:lspfactory.get()\n\n  for l:dir in l:lsp.workspaceDirectories\n    if l:dir == l:modroot\n      return\n    endif\n  endfor\n\n  \" Do not add directories that reside in the module cache if there's any\n  \" other directories already in the workspace. In such a case, adding a\n  \" module directory can potentially break jumping to definitions and finding\n  \" references if the module in the cache has a replace directive in it the\n  \" refers to a relative path.\n  if len(l:lsp.workspaceDirectories) > 0\n    let l:modcache = go#util#env('gomodcache')\n    if l:modroot[0:len(l:modcache)-1] ==# l:modcache\n      return\n    endif\n  endif\n\n  call go#lsp#AddWorkspaceDirectory(l:modroot)\nendfunction\n\nfunction! s:dedup(list)\n  let l:dict = {}\n  for l:item in a:list\n    let l:dict[l:item] = 1\n  endfor\n\n  return sort(keys(l:dict))\nendfunction\n\nfunction! s:lineinfile(fname, line) abort\n  let l:bufnr = bufnr(a:fname)\n  let l:bufinfo = getbufinfo(a:fname)\n\n  try\n    if l:bufnr == -1 || len(l:bufinfo) == 0 || l:bufinfo[0].loaded == 0\n      let l:filecontents = readfile(a:fname, '', a:line)\n    else\n      if exists('*getbufoneline')\n        let l:filecontents = [getbufoneline(a:fname, a:line)]\n      else\n        let l:filecontents = getbufline(a:fname, a:line)\n      endif\n    endif\n\n    if len(l:filecontents) == 0\n      return -1\n    endif\n\n    return l:filecontents[-1]\n  catch\n    \"call go#util#EchoError(printf('%s (line %s): %s at %s', a:fname, a:line, v:exception, v:throwpoint))\n    return -1\n  endtry\nendfunction\n\nfunction! s:within(range, line, character) abort\n  if a:line < a:range.start.line\n    return 0\n  endif\n\n  if a:line > a:range.end.line\n    return 0\n  endif\n\n  if a:line == a:range.start.line && a:character < a:range.start.character\n    return 0\n  endif\n\n  if a:line == a:range.end.line && a:character > a:range.end.character\n    return 0\n  endif\n\n  return 1\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/lsp_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nscriptencoding utf-8\n\nfunction! Test_GetSimpleTextPosition()\n    call s:getinfo('lsp text position should align with cursor position after ascii only', 'ascii')\nendfunction\n\nfunction! Test_GetMultiByteTextPosition()\n    call s:getinfo('lsp text position should align with cursor position after two place of interest symbols ⌘⌘', 'multi-byte')\nendfunction\n\nfunction! Test_GetMultipleCodeUnitTextPosition()\n    call s:getinfo('lsp text position should align with cursor position after Deseret Capital Letter Long I 𐐀', 'multi-code-units')\nendfunction\n\nfunction! s:getinfo(str, name)\n  if !go#util#has_job()\n    return\n  endif\n\n  let l:wd = getcwd()\n  try\n    let g:go_info_mode = 'gopls'\n\n    let l:tmp = gotest#write_file(a:name . '/position/position.go', [\n          \\ 'package position',\n          \\ '',\n          \\ 'func Example() {',\n          \\ \"\\tid := \" . '\"foo\"',\n          \\ \"\\tprintln(\" .'\"' . a:str . '\", id\u001f)',\n          \\ '}',\n          \\ ] )\n\n    let l:expected = 'var id string'\n    let l:actual = go#lsp#GetInfo()\n    call assert_equal(l:expected, l:actual)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunction\n\nfunc! Test_Format() abort\n  let l:wd = getcwd()\n  try\n    let expected = join(readfile(\"test-fixtures/lsp/fmt/format_golden.go\"), \"\\n\")\n    let l:tmp = gotest#load_fixture('lsp/fmt/format.go')\n\n    call go#lsp#Format()\n\n    \" this should now contain the formatted code\n    let actual = join(go#util#GetLines(), \"\\n\")\n\n    call assert_equal(expected, actual)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_Format_SingleNewline() abort\n  let l:wd = getcwd()\n  try\n    let expected = join(readfile(\"test-fixtures/lsp/fmt/format_golden.go\"), \"\\n\")\n    let l:tmp = gotest#load_fixture('lsp/fmt/newline.go')\n\n    call go#lsp#Format()\n\n    \" this should now contain the formatted code\n    let actual = join(go#util#GetLines(), \"\\n\")\n\n    call assert_equal(expected, actual)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_Format_Multibyte() abort\n  let l:wd = getcwd()\n  try\n    let expected = join(readfile(\"test-fixtures/lsp/fmt/multibyte_golden.go\"), \"\\n\")\n    let l:tmp = gotest#load_fixture('lsp/fmt/multibyte.go')\n\n    call go#lsp#Format()\n\n    \" this should now contain the formatted code\n    let actual = join(go#util#GetLines(), \"\\n\")\n\n    call assert_equal(expected, actual)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_Imports() abort\n  let l:wd = getcwd()\n  try\n    let expected = join(readfile(\"test-fixtures/lsp/imports/imports_golden.go\"), \"\\n\")\n    let l:tmp = gotest#load_fixture('lsp/imports/imports.go')\n\n    call go#lsp#Imports()\n\n    \" this should now contain the expected imports code\n    let actual = join(go#util#GetLines(), \"\\n\")\n\n    call assert_equal(expected, actual)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/mod.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nlet s:go_major_version = \"\"\n\nfunction! go#mod#Format() abort\n  \" go mod only exists in `v1.11`\n  if empty(s:go_major_version)\n    let tokens = matchlist(go#util#Exec(['go', 'version']), '\\d\\+.\\(\\d\\+\\)\\(\\.\\d\\+\\)\\? ')\n    if len(tokens) > 0\n      let s:go_major_version = str2nr(tokens[1])\n    else\n      let s:go_major_version = \"\"\n    endif\n  endif\n\n  if !empty(s:go_major_version) && s:go_major_version < \"11\"\n    call go#util#EchoError(\"Go v1.11 is required to format go.mod file\")\n    return\n  endif\n\n  let fname = fnamemodify(expand(\"%\"), ':p:gs?\\\\?/?')\n\n  \" Save cursor position and many other things.\n  let l:curw = winsaveview()\n\n  \" Write current unsaved buffer to a temp file\n  let l:tmpname = tempname() . '.mod'\n  call writefile(go#util#GetLines(), l:tmpname)\n  if go#util#IsWin()\n    let l:tmpname = tr(l:tmpname, '\\', '/')\n  endif\n\n  let current_col = col('.')\n  let l:args = ['go', 'mod', 'edit', '--fmt', l:tmpname]\n  let [l:out, l:err] = go#util#Exec(l:args)\n  let diff_offset = len(readfile(l:tmpname)) - line('$')\n\n  if l:err == 0\n    call go#mod#update_file(l:tmpname, fname)\n  else\n    let errors = s:parse_errors(fname, l:out)\n    call s:show_errors(errors)\n  endif\n\n  \" We didn't use the temp file, so clean up\n  call delete(l:tmpname)\n\n  \" Restore our cursor/windows positions.\n  call winrestview(l:curw)\n\n  \" be smart and jump to the line the new statement was added/removed\n  call cursor(line('.') + diff_offset, current_col)\n\n  \" Syntax highlighting breaks less often.\n  syntax sync fromstart\nendfunction\n\n\" update_file updates the target file with the given formatted source\nfunction! go#mod#update_file(source, target)\n  \" remove undo point caused via BufWritePre\n  try | silent undojoin | catch | endtry\n\n  let old_fileformat = &fileformat\n  if exists(\"*getfperm\")\n    \" save file permissions\n    let original_fperm = getfperm(a:target)\n  endif\n\n  call rename(a:source, a:target)\n\n  \" restore file permissions\n  if exists(\"*setfperm\") && original_fperm != ''\n    call setfperm(a:target , original_fperm)\n  endif\n\n  \" reload buffer to reflect latest changes\n  silent edit!\n\n  let &fileformat = old_fileformat\n  let &syntax = &syntax\n\n  let l:listtype = go#list#Type(\"GoModFmt\")\n\n  \" clean up previous list\n  if l:listtype == \"quickfix\"\n    let l:list_title = getqflist({'title': 1})\n  else\n    let l:list_title = getloclist(0, {'title': 1})\n  endif\n\n  if has_key(l:list_title, \"title\") && l:list_title['title'] == \"Format\"\n    call go#list#Clean(l:listtype)\n  endif\nendfunction\n\n\" parse_errors parses the given errors and returns a list of parsed errors\nfunction! s:parse_errors(filename, content) abort\n  let splitted = split(a:content, '\\n')\n\n  \" list of errors to be put into location list\n  let errors = []\n  for line in splitted\n    let tokens = matchlist(line, '^\\(.\\{-}\\):\\(\\d\\+\\):\\s*\\(.*\\)')\n    if !empty(tokens)\n      call add(errors,{\n            \\\"filename\": a:filename,\n            \\\"lnum\":     tokens[2],\n            \\\"text\":     tokens[3],\n            \\ })\n    endif\n  endfor\n\n  return errors\nendfunction\n\n\" show_errors opens a location list and shows the given errors. If the given\n\" errors is empty, it closes the the location list\nfunction! s:show_errors(errors) abort\n  let l:listtype = go#list#Type(\"GoModFmt\")\n  if !empty(a:errors)\n    call go#list#Populate(l:listtype, a:errors, 'Format')\n    call go#util#EchoError(\"GoModFmt returned error\")\n  endif\n\n  \" this closes the window if there are no errors or it opens\n  \" it if there is any\n  call go#list#Window(l:listtype, len(a:errors))\nendfunction\n\nfunction! go#mod#ToggleModFmtAutoSave() abort\n  if go#config#ModFmtAutosave()\n    call go#config#SetModFmtAutosave(0)\n    call go#util#EchoProgress(\"auto mod fmt disabled\")\n    return\n  end\n\n  call go#config#SetModFmtAutosave(1)\n  call go#util#EchoProgress(\"auto mod fmt enabled\")\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/package.vim",
    "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 provides a utility function that performs auto-completion of\n\" package names, for use by other commands.\n\n\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nlet s:goos = $GOOS\nlet s:goarch = $GOARCH\n\nif len(s:goos) == 0\n  if exists('g:golang_goos')\n    let s:goos = g:golang_goos\n  elseif has('win32') || has('win64')\n    let s:goos = 'windows'\n  elseif has('macunix')\n    let s:goos = 'darwin'\n  else\n    let s:goos = '*'\n  endif\nendif\n\nif len(s:goarch) == 0\n  if exists('g:golang_goarch')\n    let s:goarch = g:golang_goarch\n  else\n    let s:goarch = '*'\n  endif\nendif\n\nfunction! s:paths() abort\n  let dirs = []\n\n  if !exists(\"s:goroot\")\n    if executable('go')\n      let s:goroot = go#util#env(\"goroot\")\n      if go#util#ShellError() != 0\n        call go#util#EchoError('`go env GOROOT` failed')\n      endif\n    else\n      let s:goroot = $GOROOT\n    endif\n  endif\n\n  if len(s:goroot) != 0 && isdirectory(s:goroot)\n    let dirs += [s:goroot]\n  endif\n\n  let workspaces = split(go#path#Default(), go#util#PathListSep())\n  if workspaces != []\n    let dirs += workspaces\n  endif\n\n  return dirs\nendfunction\n\nfunction! s:module() abort\n  let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-m', '-f', '{{.Dir}}'])\n  if l:err != 0\n    return {}\n  endif\n  let l:dir = split(l:out, '\\n')[0]\n\n  let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-m', '-f', '{{.Path}}'])\n  if l:err != 0\n    return {}\n  endif\n  let l:path = split(l:out, '\\n')[0]\n\n  return {'dir': l:dir, 'path': l:path}\nendfunction\n\nfunction! s:vendordirs() abort\n  let l:vendorsuffix = go#util#PathSep() . 'vendor'\n  let l:module = s:module()\n  if empty(l:module)\n    let [l:root, l:err] = go#util#ExecInDir(['go', 'list', '-f', '{{.Root}}'])\n    if l:err != 0\n      return []\n    endif\n    if empty(l:root)\n      return []\n    endif\n\n    let l:root = split(l:root, '\\n')[0] . go#util#PathSep() . 'src'\n\n    let [l:dir, l:err] = go#util#ExecInDir(['go', 'list', '-f', '{{.Dir}}'])\n    if l:err != 0\n      return []\n    endif\n    let l:dir = split(l:dir, '\\n')[0]\n\n    let l:vendordirs = []\n    while l:dir != l:root\n      let l:vendordir = l:dir . l:vendorsuffix\n      if isdirectory(l:vendordir)\n        let l:vendordirs = add(l:vendordirs, l:vendordir)\n      endif\n\n      let l:dir = fnamemodify(l:dir, ':h')\n    endwhile\n\n    return l:vendordirs\n  endif\n\n  let l:vendordir = l:module.dir . l:vendorsuffix\n  if !isdirectory(l:vendordir)\n    return []\n  endif\n  return [l:vendordir]\nendfunction\n\nlet s:import_paths = {}\n\" ImportPath returns the import path of the package for current buffer. It\n\" returns -1 if the import path cannot be determined.\nfunction! go#package#ImportPath() abort\n  let l:dir = expand(\"%:p:h\")\n  if has_key(s:import_paths, dir)\n    return s:import_paths[l:dir]\n  endif\n\n  let l:importpath = go#package#FromPath(l:dir)\n  if type(l:importpath) == type(0)\n    return -1\n  endif\n\n  let s:import_paths[l:dir] = l:importpath\n\n  return l:importpath\nendfunction\n\nlet s:in_gopath = {}\n\" InGOPATH returns TRUE when the package of the current buffer is within\n\" GOPATH.\nfunction! go#package#InGOPATH() abort\n  let l:dir = expand(\"%:p:h\")\n  if has_key(s:in_gopath, dir)\n    return s:in_gopath[l:dir][0] !=#  '_'\n  endif\n\n  try\n    \" turn off module support so that `go list` will report the package name\n    \" with a leading '_' when the current buffer is not within GOPATH.\n    let Restore_modules = go#util#SetEnv('GO111MODULE', 'off')\n    let [l:out, l:err] = go#util#ExecInDir(['go', 'list'])\n    if l:err != 0\n      return 0\n    endif\n\n    let l:importpath = split(l:out, '\\n')[0]\n    if len(l:importpath) > 0\n      let s:in_gopath[l:dir] = l:importpath\n    endif\n  finally\n    call call(Restore_modules, [])\n  endtry\n\n  return len(l:importpath) > 0 && l:importpath[0] !=# '_'\nendfunction\n\n\" go#package#FromPath returns the import path of arg. -1 is returned when arg\n\" does not specify a package. -2 is returned when arg is a relative path\n\" outside of GOPATH, not in a module, and not below the current working\n\" directory. A relative path is returned when in a null module at or below the\n\" current working directory..\nfunction! go#package#FromPath(arg) abort\n  let l:path = fnamemodify(a:arg, ':p')\n  if !isdirectory(l:path)\n    let l:path = fnamemodify(l:path, ':h')\n  endif\n\n  let l:dir = go#util#Chdir(l:path)\n  try\n    if glob(\"*.go\") == \"\"\n      \" There's no Go code in this directory. We might be in a module directory\n      \" which doesn't have any code at this level. To avoid `go list` making a\n      \" bunch of HTTP requests to fetch dependencies, short-circuit `go list`\n      \" and return -1 immediately.\n      if !empty(s:module())\n        return -1\n      endif\n    endif\n    let [l:out, l:err] = go#util#Exec(['go', 'list'])\n    if l:err != 0\n      return -1\n    endif\n\n    let l:importpath = split(l:out, '\\n')[0]\n  finally\n    call go#util#Chdir(l:dir)\n  endtry\n\n  \" go list returns '_CURRENTDIRECTORY' if the directory is in a null module\n  \" (i.e. neither in GOPATH nor in a module). Return a relative import path\n  \" if possible or an error if that is the case.\n  if l:importpath[0] ==# '_'\n    let l:relativeimportpath = fnamemodify(l:importpath[1:], ':.')\n    if go#util#IsWin()\n      let l:relativeimportpath = substitute(l:relativeimportpath, '\\\\', '/', 'g')\n    endif\n\n    if l:relativeimportpath == l:importpath[1:]\n      return '.'\n    endif\n\n    if l:relativeimportpath[0] == '/'\n      return -2\n    endif\n\n    let l:importpath= printf('./%s', l:relativeimportpath)\n  endif\n\n  return l:importpath\nendfunction\n\nfunction! go#package#CompleteMembers(package, member) abort\n  let [l:content, l:err] = go#util#Exec(['go', 'doc', a:package])\n  if l:err || !len(content)\n    return []\n  endif\n\n  let lines = filter(split(content, \"\\n\"),\"v:val !~ '^\\\\s\\\\+$'\")\n  try\n    let mx1 = '^\\s\\+\\(\\S+\\)\\s\\+=\\s\\+.*'\n    let mx2 = '^\\%(const\\|var\\|type\\|func\\) \\([A-Z][^ (]\\+\\).*'\n    let candidates = map(filter(copy(lines), 'v:val =~ mx1'),\n          \\ 'substitute(v:val, mx1, \"\\\\1\", \"\")')\n          \\ + map(filter(copy(lines), 'v:val =~ mx2'),\n          \\ 'substitute(v:val, mx2, \"\\\\1\", \"\")')\n    return filter(candidates, '!stridx(v:val, a:member)')\n  catch\n    return []\n  endtry\nendfunction\n\nfunction! go#package#Complete(ArgLead, CmdLine, CursorPos) abort\n  let words = split(a:CmdLine, '\\s\\+', 1)\n\n  \" do not complete package members for these commands\n  let neglect_commands = [\"GoImportAs\", \"GoGuruScope\"]\n\n  if len(words) > 2 && index(neglect_commands, words[0]) == -1\n    \" Complete package members\n    return go#package#CompleteMembers(words[1], words[2])\n  endif\n\n  let dirs = s:paths()\n  let module = s:module()\n\n  if len(dirs) == 0 && empty(module)\n    \" should not happen\n    return []\n  endif\n\n  let vendordirs = s:vendordirs()\n\n  let l:modcache = go#util#env('gomodcache')\n\n  let ret = {}\n  for dir in dirs\n    \" this may expand to multiple lines\n    let root = split(expand(dir . '/pkg/' . s:goos . '_' . s:goarch), \"\\n\")\n    if l:modcache != ''\n      let root = add(root, l:modcache)\n    else\n      let root = add(root, expand(dir . '/pkg/mod'))\n    endif\n    let root = add(root, expand(dir . '/src'), )\n    let root = extend(root, vendordirs)\n    let root = add(root, module)\n    for item in root\n      \" item may be a dictionary when operating in a module.\n      if type(item) == type({})\n        if empty(item)\n          continue\n        endif\n        let dir = item.dir\n        let path = item.path\n      else\n        let dir = item\n        let path = item\n      endif\n\n      if !empty(module) && dir ==# module.dir\n        if stridx(a:ArgLead, module.path) == 0\n          if len(a:ArgLead) != len(module.path)\n            let glob = globpath(module.dir, substitute(a:ArgLead, module.path . '/\\?', '', '').'*')\n          else\n            let glob = module.dir\n          endif\n        elseif stridx(module.path, a:ArgLead) == 0 && stridx(module.path, '/', len(a:ArgLead)) < 0\n          \" use the module directory when module.path begins wih a:ArgLead and\n          \" module.path does not have any path segments after a:ArgLead.\n          let glob = module.dir\n        else\n          continue\n        endif\n      else\n        let glob = globpath(dir, a:ArgLead.'*')\n      endif\n      for candidate in split(glob)\n        if isdirectory(candidate)\n          \" TODO(bc): use wildignore instead of filtering out vendor\n          \" directories manually?\n          if fnamemodify(candidate, ':t') == 'vendor'\n            continue\n          endif\n          \" if path contains version info, strip it out\n          let vidx = strridx(candidate, '@')\n          if vidx >= 0\n            let candidate = strpart(candidate, 0, vidx)\n          endif\n          let candidate .= '/'\n        elseif candidate !~ '\\.a$'\n          continue\n        endif\n\n        if dir !=# path\n          let candidate = substitute(candidate, '^' . dir, path, 'g')\n        else\n          let candidate = candidate[len(dir)+1:]\n        endif\n        \" replace a backslash with a forward slash and drop .a suffixes\n        let candidate = substitute(substitute(candidate, '[\\\\]', '/', 'g'),\n                          \\ '\\.a$', '', 'g')\n\n        \" without this the result can have duplicates in form of\n        \" 'encoding/json' and '/encoding/json/'\n        let candidate = go#util#StripPathSep(candidate)\n\n        let ret[candidate] = candidate\n      endfor\n    endfor\n  endfor\n  return sort(keys(ret))\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/package_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunc! Test_Complete_GOPATH_simple() abort\n  let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/package'\n  silent exe 'edit ' . $GOPATH . '/src/package/package.go'\n  call s:complete('package', ['package'])\n  call delete(printf('%s/pkg', $GOPATH), 'rf')\nendfunc\n\nfunc! Test_Complete_Module_simple() abort\n  silent exe 'edit ' . fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/package/src/package/package.go'\n  call s:complete('package', ['package'])\nendfunc\n\nfunc! Test_Complete_GOPATH_subdirs() abort\n  let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/package'\n  silent exe 'edit ' . $GOPATH . '/src/package/package.go'\n  call s:complete('package/', ['package/bar', 'package/baz'])\n  call delete(printf('%s/pkg', $GOPATH), 'rf')\nendfunc\n\nfunc! Test_Complete_Module_subdirs() abort\n  silent exe 'edit ' . fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/package/src/package/package.go'\n  call s:complete('package/', ['package/bar', 'package/baz'])\nendfunc\n\nfunc! Test_Complete_GOPATH_baronly() abort\n  let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/package'\n  silent exe 'edit ' . $GOPATH . '/src/package/package.go'\n  call s:complete('package/bar', ['package/bar'])\n  call delete(printf('%s/pkg', $GOPATH), 'rf')\nendfunc\n\nfunc! Test_Complete_Module_baronly() abort\n  silent exe 'edit ' . fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/package/src/package/package.go'\n  call s:complete('package/bar', ['package/bar'])\nendfunc\n\nfunc! Test_Complete_GOPATH_vendor() abort\n  let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/package'\n  silent exe 'edit ' . $GOPATH . '/src/package/package.go'\n  call s:complete('foo', ['foo'])\n  call delete(printf('%s/pkg', $GOPATH), 'rf')\nendfunc\n\nfunc! Test_Complete_Module_vendor() abort\n  silent exe 'edit ' . fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/package/src/package/package.go'\n  call s:complete('foo', ['foo'])\nendfunc\n\nfunc! s:complete(arglead, expected) abort\n  let l:candidates = go#package#Complete(a:arglead, '', 1)\n  call assert_equal(a:expected, l:candidates)\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/path.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\n\" initial_go_path is used to store the initial GOPATH that was set when Vim\n\" was started. It's used with :GoPathClear to restore the GOPATH when the user\n\" changed it explicitly via :GoPath. Initially it's empty. It's being set when\n\" :GoPath is used\nlet s:initial_go_path = \"\"\n\n\" GoPath sets or echos the current GOPATH. If no arguments are passed it\n\" echoes the current GOPATH, if an argument is passed it replaces the current\n\" GOPATH with it. If two double quotes are passed (the empty string in go),\n\" it'll clear the GOPATH and will restore to the initial GOPATH.\nfunction! go#path#GoPath(...) abort\n  \" no argument, show GOPATH\n  if len(a:000) == 0\n    echo go#path#Default()\n    return\n  endif\n\n  \" we have an argument, replace GOPATH\n  \" clears the current manually set GOPATH and restores it to the\n  \" initial GOPATH, which was set when Vim was started.\n  if len(a:000) == 1 && a:1 == '\"\"'\n    if !empty(s:initial_go_path)\n      let $GOPATH = s:initial_go_path\n      let s:initial_go_path = \"\"\n    endif\n\n    call go#util#EchoInfo(\"GOPATH restored to \". $GOPATH)\n    return\n  endif\n\n  call go#util#EchoInfo(\"GOPATH changed to \". a:1)\n  let s:initial_go_path = $GOPATH\n  let $GOPATH = a:1\nendfunction\n\n\" Default returns the default GOPATH. If GOPATH is not set, it uses the\n\" default GOPATH set starting with Go 1.8. This GOPATH can be retrieved via\n\" 'go env GOPATH'\nfunction! go#path#Default() abort\n  if $GOPATH == \"\"\n    \" use default GOPATH via go env\n    return go#util#env(\"gopath\")\n  endif\n\n  return $GOPATH\nendfunction\n\n\" s:HasPath checks whether the given path exists in GOPATH environment variable\n\" or not\nfunction! s:HasPath(path) abort\n  let go_paths = split(go#path#Default(), go#util#PathListSep())\n  let last_char = strlen(a:path) - 1\n\n  \" check cases of '/foo/bar/' and '/foo/bar'\n  if a:path[last_char] == go#util#PathSep()\n    let withSep = a:path\n    let noSep = strpart(a:path, 0, last_char)\n  else\n    let withSep = a:path . go#util#PathSep()\n    let noSep = a:path\n  endif\n\n  let hasA = index(go_paths, withSep) != -1\n  let hasB = index(go_paths, noSep) != -1\n  return hasA || hasB\nendfunction\n\n\" BinPath returns the binary path of installed go tools.\nfunction! go#path#BinPath() abort\n  let l:bin_path = go#config#BinPath()\n  if l:bin_path isnot \"\"\n    return l:bin_path\n  endif\n\n  \" check if our global custom path is set, if not check if GOBIN is set so\n  \" we can use it, otherwise use default GOPATH\n  let l:bin_path = go#util#env('gobin')\n  if l:bin_path isnot ''\n    let l:bin_path = $GOBIN\n  else\n    let l:go_paths = split(go#path#Default(), go#util#PathListSep())\n    if len(l:go_paths) == 0\n      return '' \"nothing found\n    endif\n    let l:bin_path = expand(l:go_paths[0] . '/bin/')\n  endif\n\n  return l:bin_path\nendfunction\n\n\" CheckBinPath checks whether the given binary exists or not and returns the\n\" path of the binary, respecting the go_bin_path and go_search_bin_path_first\n\" settings. It returns an empty string if the binary doesn't exist.\nfunction! go#path#CheckBinPath(binpath) abort\n  \" remove whitespaces if user applied something like 'goimports   '\n  let binpath = substitute(a:binpath, '^\\s*\\(.\\{-}\\)\\s*$', '\\1', '')\n\n  \" save original path\n  let old_path = $PATH\n\n  \" check if we have an appropriate bin_path\n  let go_bin_path = go#path#BinPath()\n  if !empty(go_bin_path)\n    \" append our GOBIN and GOPATH paths and be sure they can be found there...\n    \" let us search in our GOBIN and GOPATH paths\n    \" respect the ordering specified by go_search_bin_path_first\n    if go#config#SearchBinPathFirst()\n      let $PATH = go_bin_path . go#util#PathListSep() . $PATH\n    else\n      let $PATH = $PATH . go#util#PathListSep() . go_bin_path\n    endif\n  endif\n\n  \" if it's in PATH just return it\n  if executable(binpath)\n    if exists('*exepath')\n      let binpath = exepath(binpath)\n    endif\n    let $PATH = old_path\n\n    if go#util#IsUsingCygwinShell() == 1\n      return s:CygwinPath(binpath)\n    endif\n\n    return binpath\n  endif\n\n  \" just get the basename\n  let basename = fnamemodify(binpath, \":t\")\n  if !executable(basename)\n    call go#util#EchoError(printf(\"could not find '%s'. Run :GoInstallBinaries to fix it\", basename))\n\n    \" restore back!\n    let $PATH = old_path\n    return \"\"\n  endif\n\n  let $PATH = old_path\n\n  if go#util#IsUsingCygwinShell() == 1\n    return s:CygwinPath(a:binpath)\n  endif\n\n  return go_bin_path . go#util#PathSep() . basename\nendfunction\n\nfunction! s:CygwinPath(path)\n   return substitute(a:path, '\\\\', '/', \"g\")\nendfunction\n\n\" go#path#ToURI converts path to a file URI. path should be an absolute path.\n\" Relative paths cannot be properly converted to a URI; when path is a\n\" relative path, the file scheme will not be prepended.\nfunction! go#path#ToURI(path)\n  let l:absolute = !go#util#IsWin() && a:path[0] is# '/'\n  let l:prefix = ''\n  let l:path = a:path\n\n  if go#util#IsWin() && l:path[1:2] is# ':\\'\n    let l:absolute = 1\n    let l:prefix = '/' . l:path[0:1]\n    let l:path = l:path[2:]\n  endif\n\n  return substitute(\n  \\   (l:absolute ? 'file://' : '') . l:prefix . go#uri#EncodePath(l:path),\n  \\   '\\\\',\n  \\   '/',\n  \\   'g',\n  \\)\nendfunction\n\nfunction! go#path#FromURI(uri) abort\n    let l:i = len('file://')\n    let l:encoded_path = a:uri[: l:i - 1] is# 'file://' ? a:uri[l:i :] : a:uri\n\n    let l:path = go#uri#Decode(l:encoded_path)\n\n    \" If the path is like /C:/foo/bar, it should be C:\\foo\\bar instead.\n    if go#util#IsWin() && l:path =~# '^/[a-zA-Z]:'\n        let l:path = substitute(l:path[1:], '/', '\\\\', 'g')\n    endif\n\n    return l:path\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/play.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! go#play#Share(count, line1, line2) abort\n  if !executable('curl')\n    call go#util#EchoError('cannot share: curl cannot be found')\n    return\n  endif\n\n  let content = join(getline(a:line1, a:line2), \"\\n\")\n  let share_file = tempname()\n  call writefile(split(content, \"\\n\"), share_file, \"b\")\n\n  let l:cmd = ['curl', '-s',\n        \\ '-H', 'Content-Type: text/plain; charset=utf-8',\n        \\ '-X', 'POST', 'https://go.dev/_/share',\n        \\ '--data-binary', '@' . l:share_file]\n  let [l:snippet_id, l:err] = go#util#Exec(l:cmd)\n\n  \" we can remove the temp file because it's now posted.\n  call delete(share_file)\n\n  if l:err != 0\n    call go#util#EchoError(['A error has occurred. Run this command to see what the problem is:', go#util#Shelljoin(l:cmd)])\n    return\n  endif\n\n  let url = printf(\"https://go.dev/play/p/%s\", snippet_id)\n\n  \" copy to clipboard\n  if has('unix') && !has('xterm_clipboard') && !has('clipboard')\n    let @\" = url\n  else\n    let @+ = url\n  endif\n\n  if go#config#PlayOpenBrowser()\n    call go#util#OpenBrowser(url)\n  endif\n\n  call go#util#EchoInfo('snippet uploaded: ' . url)\nendfunction\n\n\nfunction! s:get_visual_content() abort\n  let save_regcont = @\"\n  let save_regtype = getregtype('\"')\n  silent! normal! gvy\n  let content = @\"\n  call setreg('\"', save_regcont, save_regtype)\n  return content\nendfunction\n\n\" modified version of\n\" http://stackoverflow.com/questions/1533565/how-to-get-visually-selected-text-in-vimscript\n\" another function that returns the content of visual selection, it's not used\n\" but might be useful in the future\nfunction! s:get_visual_selection() abort\n  let [lnum1, col1] = getpos(\"'<\")[1:2]\n  let [lnum2, col2] = getpos(\"'>\")[1:2]\n\n  \" check if the the visual mode is used before\n  if lnum1 == 0  || lnum2 == 0  || col1 == 0  || col2 == 0\n    return\n  endif\n\n  let lines = getline(lnum1, lnum2)\n  let lines[-1] = lines[-1][: col2 - (&selection == 'inclusive' ? 1 : 2)]\n  let lines[0] = lines[0][col1 - 1:]\n  return join(lines, \"\\n\")\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/promise.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nscriptencoding utf-8\n\n\" New returns a promise. A promise's primary purpose is to make async jobs\n\" synchronous by awaiting fn.\n\"\n\" A promise is a dictionary with two keys:\n\"   'wrapper':\n\"     A function that wraps fn. It can be used in place of fn.\n\"   'await':\n\"     A function that waits for wrapper to be called and returns the value\n\"     returned by fn. Returns default if timeout expires.\nfunction! go#promise#New(fn, timeout, default) abort\n  let l:state = {}\n\n  \" explicitly bind to state so that within l:promise's methods, self will\n  \" always refer to state. See :help Partial for more information.\n  return {\n        \\ 'wrapper': function('s:wrapper', [a:fn, a:default], l:state),\n        \\ 'await': function('s:await', [a:timeout, a:default], l:state),\n  \\ }\nendfunction\n\nfunction! s:wrapper(fn, default, ...) dict\n  try\n    let self.retval = call(a:fn, a:000)\n  catch\n    let self.retval = substitute(v:exception, '^Vim', '', '')\n    let self.exception = 1\n  endtry\n  return self.retval\nendfunction\n\nfunction! s:await(timeout, default) dict\n  let l:timer = timer_start(a:timeout, function('s:setretval', [a:default], self))\n  while !has_key(self, 'retval')\n    sleep 50m\n  endwhile\n  call timer_stop(l:timer)\n\n  if get(self, 'exception', 0)\n    throw self.retval\n  endif\n  return self.retval\nendfunction\n\nfunction! s:setretval(val, timer) dict\n  let self.retval = a:val\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/promise_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunc! Test_PromiseNew() abort\n\tlet l:sut = go#promise#New(function('s:work', []), 100, -1)\n\tcall assert_true(has_key(l:sut, 'wrapper'))\n\tcall assert_true(has_key(l:sut, 'await'))\nendfunc\n\nfunc! Test_PromiseAwait() abort\n\tlet l:expected = 1\n\tlet l:default = -1\n\tlet l:sut = go#promise#New(function('s:work', [l:expected]), 100, l:default)\n\n\tcall timer_start(10, l:sut.wrapper)\n\n\tlet l:actual = call(l:sut.await, [])\n\tcall assert_equal(l:expected, l:actual)\nendfunc\n\nfunc! Test_PromiseAwait_Timeout() abort\n\tlet l:desired = 1\n\tlet l:expected = -1\n\tlet l:sut = go#promise#New(function('s:work', [l:desired]), 10, l:expected)\n\n\tcall timer_start(100, l:sut.wrapper)\n\n\tlet l:actual = call(l:sut.await, [])\n\tcall assert_equal(l:expected, l:actual)\nendfunc\n\nfunc! s:work(val, timer)\n\treturn a:val\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/referrers.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! go#referrers#Referrers(selected) abort\n  let l:mode = go#config#ReferrersMode()\n  if l:mode == 'gopls'\n    if !go#config#GoplsEnabled()\n      call go#util#EchoError(\"go_referrers_mode is 'gopls', but gopls is disabled\")\n      return\n    endif\n    let [l:line, l:col] = getpos('.')[1:2]\n    let [l:line, l:col] = go#lsp#lsp#Position(l:line, l:col)\n    let l:fname = expand('%:p')\n    call go#lsp#Referrers(l:fname, l:line, l:col, funcref('s:parse_output'))\n    return\n  else\n    call go#util#EchoWarning('unknown value for g:go_referrers_mode')\n  endif\nendfunction\n\n\" This uses Vim's errorformat to parse the output and put it into a quickfix\n\" or locationlist.\nfunction! s:parse_output(exit_val, output) abort\n  if a:exit_val\n    call go#util#EchoError(a:output)\n    return\n  endif\n\n  let errformat = \",%f:%l:%c:\\ %m\"\n  let l:listtype = go#list#Type(\"GoReferrers\")\n  call go#list#ParseFormat(l:listtype, errformat, a:output, 'referrers', 0)\n\n  let errors = go#list#Get(l:listtype)\n  call go#list#Window(l:listtype, len(errors))\nendfunction\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/rename.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! go#rename#Rename(bang, ...) abort\n  let to_identifier = \"\"\n  if a:0 == 0\n    let ask = printf(\"vim-go: rename '%s' to: \", expand(\"<cword>\"))\n    let prefill = go#config#GorenamePrefill()\n    if prefill != ''\n      let to_identifier = input(ask, eval(prefill))\n    else\n      let to_identifier = input(ask)\n    endif\n    redraw!\n    if empty(to_identifier)\n      return\n    endif\n  else\n    let to_identifier = a:1\n  endif\n\n  let l:bin = go#config#RenameCommand()\n\n  \" return with a warning if the bin doesn't exist\n  let bin_path = go#path#CheckBinPath(substitute(l:bin, 'gopls rename$', 'gopls', ''))\n  if empty(bin_path)\n    return\n  endif\n\n  if l:bin == 'gopls'\n    call go#lsp#Rename(to_identifier)\n    return\n  endif\n\n  let fname = expand('%:p')\n  let pos = go#util#OffsetCursor()\n\n  let args = []\n  if l:bin == 'gorename'\n    let offset = printf('%s:#%d', fname, pos)\n    let l:args = extend(l:args, ['-tags', go#config#BuildTags(), '-offset', offset, '-to', to_identifier])\n  elseif l:bin == 'gopls rename'\n    let offset = printf('%s:#%d', fname, pos)\n    let l:args = extend(l:args, ['rename', '-write', offset, to_identifier])\n  else\n    call go#util#EchoWarning('unexpected rename command')\n  endif\n\n  let l:cmd = extend([l:bin_path], l:args)\n\n  if go#util#has_job()\n    call s:rename_job({\n          \\ 'cmd': cmd,\n          \\ 'bang': a:bang,\n          \\})\n    return\n  endif\n\n  let l:wd = go#util#ModuleRoot()\n  if l:wd == -1\n    let l:wd = expand(\"%:p:h\")\n  endif\n\n  let [l:out, l:err] = go#util#ExecInWorkDir(l:cmd, l:wd)\n  call s:parse_errors(l:err, a:bang, split(l:out, '\\n'))\nendfunction\n\nfunction s:rename_job(args)\n  let l:job_opts = {\n        \\ 'bang': a:args.bang,\n        \\ 'for': 'GoRename',\n        \\ 'statustype': 'gorename',\n        \\ }\n\n  \" autowrite is not enabled for jobs\n  call go#cmd#autowrite()\n  let l:cbs = go#job#Options(l:job_opts)\n\n  let l:wd = go#util#ModuleRoot()\n  if l:wd != -1\n    let l:cbs.cwd = l:wd\n  endif\n\n  \" wrap l:cbs.exit_cb in s:exit_cb.\n  let l:cbs.exit_cb = funcref('s:exit_cb', [l:cbs.exit_cb])\n\n  call go#job#Start(a:args.cmd, l:cbs)\nendfunction\n\nfunction! s:reload_changed() abort\n  \" reload all files to reflect the new changes. We explicitly call\n  \" checktime to trigger a reload of all files. See\n  \" http://www.mail-archive.com/vim@vim.org/msg05900.html for more info\n  \" about the autoread bug\n  let current_autoread = &autoread\n  set autoread\n  silent! checktime\n  let &autoread = current_autoread\nendfunction\n\n\" s:exit_cb reloads any changed buffers and then calls next.\nfunction! s:exit_cb(next, job, exitval) abort\n  call s:reload_changed()\n  call call(a:next, [a:job, a:exitval])\nendfunction\n\nfunction s:parse_errors(exit_val, bang, out)\n  \" reload all files to reflect the new changes. We explicitly call\n  \" checktime to trigger a reload of all files. See\n  \" http://www.mail-archive.com/vim@vim.org/msg05900.html for more info\n  \" about the autoread bug\n  let current_autoread = &autoread\n  set autoread\n  silent! checktime\n  let &autoread = current_autoread\n\n  let l:listtype = go#list#Type(\"GoRename\")\n  if a:exit_val != 0\n    let errors = go#util#ParseErrors(a:out)\n    call go#list#Populate(l:listtype, errors, 'Rename')\n    call go#list#Window(l:listtype, len(errors))\n    if !empty(errors) && !a:bang\n      call go#list#JumpToFirst(l:listtype)\n    elseif empty(errors)\n      \" failed to parse errors, output the original content\n      call go#util#EchoError(a:out)\n    endif\n\n    return\n  endif\n\n  \" strip out newline on the end that gorename puts. If we don't remove, it\n  \" will trigger the 'Hit ENTER to continue' prompt\n  call go#list#Clean(l:listtype)\n  call go#util#EchoSuccess(a:out[0])\n\n  \" refresh the buffer so we can see the new content\n  silent execute \":e\"\nendfunction\n\n\" Commandline completion: original, unexported camelCase, and exported\n\" CamelCase.\nfunction! go#rename#Complete(lead, cmdline, cursor)\n  let l:word = expand('<cword>')\n  return filter(uniq(sort(\n        \\ [l:word, go#util#camelcase(l:word), go#util#pascalcase(l:word)])),\n        \\ 'strpart(v:val, 0, len(a:lead)) == a:lead')\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/sameids.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! go#sameids#SameIds(showstatus) abort\n  if !go#config#GoplsEnabled()\n    call go#util#EchoError(\"GoSameIds requires gopls, but gopls is disabled\")\n    return\n  endif\n\n  \" check if the version of Vim being tested supports matchaddpos()\n  if !exists(\"*matchaddpos\")\n    call go#util#EchoError(\"GoSameIds requires 'matchaddpos'. Update your Vim/Neovim version.\")\n    return\n  endif\n\n  \" check if the version of Vim being tested supports json_decode()\n  if !exists(\"*json_decode\")\n    call go#util#EchoError(\"GoSameIds requires 'json_decode'. Update your Vim/Neovim version.\")\n    return\n  endif\n\n  let [l:line, l:col] = getpos('.')[1:2]\n  let [l:line, l:col] = go#lsp#lsp#Position(l:line, l:col)\n  call go#lsp#SameIDs(0, expand('%:p'), l:line, l:col, funcref('s:same_ids_highlight'))\nendfunction\n\nfunction! s:same_ids_highlight(exit_val, result) abort\n  call go#sameids#ClearSameIds() \" clear at the start to reduce flicker\n\n  if type(a:result) != type({}) && !go#config#AutoSameids()\n    call go#util#EchoError(\"malformed same id result\")\n    return\n  endif\n\n  if !has_key(a:result, 'sameids') || len(a:result.sameids) == 0\n    if !go#config#AutoSameids()\n      call go#util#EchoError(\"no references found for the given identifier\")\n    endif\n    return\n  endif\n\n  let same_ids = a:result['sameids']\n\n  \" highlight the lines\n  let l:matches = []\n  for pos in same_ids\n    let poslen = pos[2] - pos[1]\n    let l:matches = add(l:matches, [pos[0], pos[1], poslen])\n  endfor\n\n  call go#util#HighlightPositions('goSameId', l:matches)\n\n  if go#config#AutoSameids()\n    \" re-apply SameIds at the current cursor position at the time the buffer\n    \" is redisplayed: e.g. :edit, :GoRename, etc.\n    augroup vim-go-sameids\n      autocmd! * <buffer>\n      if has('textprop')\n        autocmd BufReadPost <buffer> nested call go#sameids#SameIds(0)\n      else\n        autocmd BufWinEnter <buffer> nested call go#sameids#SameIds(0)\n      endif\n    augroup end\n  endif\nendfunction\n\n\" ClearSameIds returns 0 when it removes goSameId groups and non-zero if no\n\" goSameId groups are found.\nfunction! go#sameids#ClearSameIds() abort\n  let l:cleared = go#util#ClearHighlights('goSameId')\n\n  if !l:cleared\n    return 1\n  endif\n\n  \" remove the autocmds we defined\n  augroup vim-go-sameids\n    autocmd! * <buffer>\n  augroup end\n\n  return 0\nendfunction\n\nfunction! go#sameids#ToggleSameIds() abort\n  if go#sameids#ClearSameIds() != 0\n    call go#sameids#SameIds(1)\n  endif\nendfunction\n\nfunction! go#sameids#AutoToggleSameIds() abort\n  if go#config#AutoSameids()\n    call go#util#EchoProgress(\"sameids auto highlighting disabled\")\n    call go#sameids#ClearSameIds()\n    call go#config#SetAutoSameids(0)\n  else\n    call go#util#EchoSuccess(\"sameids auto highlighting enabled\")\n    call go#config#SetAutoSameids(1)\n  endif\n  call go#auto#update_autocmd()\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/statusline.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\n\" Statusline\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\n\" s:statuses is a global reference to all statuses. It stores the statuses per\n\" import paths (map[string]status), where each status is unique per its\n\" type. Current status dict is in form:\n\" {\n\"   'desc'        : 'Job description',\n\"   'state'       : 'Job state, such as success, failure, etc..',\n\"   'type'        : 'Job type, such as build, test, etc..'\n\"   'created_at'  : 'Time it was created as seconds since 1st Jan 1970'\n\" }\nlet s:statuses = {}\n\n\" timer_id for cleaner\nlet s:timer_id = 0\n\n\" last_status stores the last generated text per status\nlet s:last_status = \"\"\n\n\" Show returns the current status of the job for 20 seconds (configurable). It\n\" displays it in form of 'desc: [type|state]' if there is any state available,\n\" if not it returns an empty string. This function should be plugged directly\n\" into the statusline.\nfunction! go#statusline#Show() abort\n  \" lazy initialization of the cleaner\n  if !s:timer_id\n    let interval = go#config#StatuslineDuration()\n    let s:timer_id = timer_start(interval, function('go#statusline#Clear'), {'repeat': -1})\n  endif\n\n  \" nothing to show\n  if empty(s:statuses)\n    return ''\n  endif\n\n  let status_dir =  expand('%:p:h')\n\n  if !has_key(s:statuses, status_dir)\n    return ''\n  endif\n\n  let status = s:statuses[status_dir]\n  if !has_key(status, 'desc') || !has_key(status, 'state') || !has_key(status, 'type')\n    return ''\n  endif\n\n  let status_text = printf(\"[%s|%s]\", status.type, status.state)\n  if empty(status_text)\n    return ''\n  endif\n\n  \" only update highlight if status has changed.\n  if status_text != s:last_status\n    if status.state =~ \"success\" || status.state =~ \"finished\" || status.state =~ \"pass\" || status.state =~ 'initialized'\n      hi goStatusLineColor cterm=bold ctermbg=76 ctermfg=22 guibg=#5fd700 guifg=#005f00\n    elseif status.state =~ \"started\" || status.state =~ \"analysing\" || status.state =~ \"compiling\" || status.state =~ 'initializing'\n      hi goStatusLineColor cterm=bold ctermbg=208 ctermfg=88 guibg=#ff8700 guifg=#870000\n    elseif status.state =~ \"failed\"\n      hi goStatusLineColor cterm=bold ctermbg=196 ctermfg=52 guibg=#ff0000 guifg=#5f0000\n    endif\n  endif\n\n  let s:last_status = status_text\n  return status_text\nendfunction\n\n\" Update updates (adds) the statusline for the given status_dir with the\n\" given status dict. It overrides any previously set status.\nfunction! go#statusline#Update(status_dir, status) abort\n  let a:status.created_at = reltime()\n  let s:statuses[a:status_dir] = a:status\n\n  \" force to update the statusline, otherwise the user needs to move the\n  \" cursor\n  exe 'let &ro = &ro'\n\n  \" before we stop the timer, check if we have any previous jobs to be cleaned\n  \" up. Otherwise every job will reset the timer when this function is called\n  \" and thus old jobs will never be cleaned\n  call s:clear()\n\n  \" also reset the timer, so the user has time to see it in the statusline.\n  \" Setting the timer_id to 0 will cause a new timer to be created the next\n  \" time the go#statusline#Show() is called.\n  call timer_stop(s:timer_id)\n  let s:timer_id = 0\nendfunction\n\n\" Clear clears all currently stored statusline data. The timer_id argument is\n\" just a placeholder so we can pass it to a timer_start() function if needed.\nfunction! go#statusline#Clear(timer_id) abort\n  call s:clear()\nendfunction\n\nfunction! s:clear()\n  for [status_dir, status] in items(s:statuses)\n    let elapsed_time = reltimestr(reltime(status.created_at))\n    \" strip whitespace\n    let elapsed_time = substitute(elapsed_time, '^\\s*\\(.\\{-}\\)\\s*$', '\\1', '')\n\n    if str2nr(elapsed_time) > 10\n      call remove(s:statuses, status_dir)\n    endif\n  endfor\n\n  if len(s:statuses) == 0\n    let s:statuses = {}\n  endif\n\n  \" force to update the statusline, otherwise the user needs to move the\n  \" cursor\n  exe 'let &ro = &ro'\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/tags.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\n\" mapped to :GoAddTags\nfunction! go#tags#Add(start, end, count, ...) abort\n  let fname = fnamemodify(expand(\"%\"), ':p:gs?\\\\?/?')\n  let offset = 0\n  if a:count == -1\n    let offset = go#util#OffsetCursor()\n  endif\n\n  let test_mode = 0\n  call call(\"go#tags#run\", [a:start, a:end, offset, \"add\", fname, test_mode] + a:000)\nendfunction\n\n\" mapped to :GoRemoveTags\nfunction! go#tags#Remove(start, end, count, ...) abort\n  let fname = fnamemodify(expand(\"%\"), ':p:gs?\\\\?/?')\n  let offset = 0\n  if a:count == -1\n    let offset = go#util#OffsetCursor()\n  endif\n\n  let test_mode = 0\n  call call(\"go#tags#run\", [a:start, a:end, offset, \"remove\", fname, test_mode] + a:000)\nendfunction\n\n\" run runs gomodifytag. This is an internal test so we can test it\nfunction! go#tags#run(start, end, offset, mode, fname, test_mode, ...) abort\n  \" do not split this into multiple lines, somehow tests fail in that case\n  let args = {'mode': a:mode,'start': a:start,'end': a:end,'offset': a:offset,'fname': a:fname,'cmd_args': a:000}\n\n  if &modified\n    let args[\"modified\"] = 1\n  endif\n\n  let l:result = s:create_cmd(args)\n  if has_key(result, 'err')\n    call go#util#EchoError(result.err)\n    return -1\n  endif\n\n  if &modified\n    let filename = expand(\"%:p:gs!\\\\!/!\")\n    let content  = join(go#util#GetLines(), \"\\n\")\n    let in = filename . \"\\n\" . strlen(content) . \"\\n\" . content\n    let [l:out, l:err] = go#util#Exec(l:result.cmd, in)\n  else\n    let [l:out, l:err] = go#util#Exec(l:result.cmd)\n  endif\n\n  if l:err != 0\n    call go#util#EchoError(out)\n    return\n  endif\n\n  if a:test_mode\n    exe 'edit ' . a:fname\n  endif\n\n  call s:write_out(out)\n\n  if a:test_mode\n    exe 'write! ' . a:fname\n  endif\nendfunc\n\n\n\" write_out writes back the given output to the current buffer\nfunc s:write_out(out) abort\n  \" nothing to do\n  if empty(a:out) || type(a:out) != type(\"\")\n    return\n  endif\n\n  \" not a json output\n  if a:out[0] !=# '{'\n    return\n  endif\n\n  let result = json_decode(a:out)\n  if type(result) != type({})\n    call go#util#EchoError(printf(\"malformed output from gomodifytags: %s\", a:out))\n    return\n  endif\n\n  let lines = result['lines']\n  let start_line = result['start']\n  let end_line = result['end']\n\n  let index = 0\n  for line in range(start_line, end_line)\n    call setline(line, lines[index])\n    let index += 1\n  endfor\n\n  if has_key(result, 'errors')\n    let l:winnr = winnr()\n    let l:listtype = go#list#Type(\"GoModifyTags\")\n    call go#list#ParseFormat(l:listtype, \"%f:%l:%c:%m\", result['errors'], \"gomodifytags\", 0)\n    call go#list#Window(l:listtype, len(result['errors']))\n\n    \"prevent jumping to quickfix list\n    exe l:winnr . \"wincmd w\"\n  endif\nendfunc\n\n\n\" create_cmd returns a dict that contains the command to execute gomodifytags\nfunc s:create_cmd(args) abort\n  if !exists(\"*json_decode\")\n    return {'err': \"requires 'json_decode'. Update your Vim/Neovim version.\"}\n  endif\n\n  let bin_path = go#path#CheckBinPath('gomodifytags')\n  if empty(bin_path)\n    return {'err': \"gomodifytags does not exist\"}\n  endif\n\n  let l:start = a:args.start\n  let l:end = a:args.end\n  let l:offset = a:args.offset\n  let l:mode = a:args.mode\n  let l:cmd_args = a:args.cmd_args\n  let l:modifytags_transform = go#config#AddtagsTransform()\n  let l:modifytags_skip_unexported = go#config#AddtagsSkipUnexported()\n\n  \" start constructing the command\n  let cmd = [bin_path]\n  call extend(cmd, [\"-format\", \"json\"])\n  call extend(cmd, [\"-file\", a:args.fname])\n  call extend(cmd, [\"-transform\", l:modifytags_transform])\n\n  if l:modifytags_skip_unexported\n    call extend(cmd, [\"-skip-unexported\"])\n  endif\n\n  if has_key(a:args, \"modified\")\n    call add(cmd, \"-modified\")\n  endif\n\n  if l:offset != 0\n    call extend(cmd, [\"-offset\", l:offset])\n  else\n    let range = printf(\"%d,%d\", l:start, l:end)\n    call extend(cmd, [\"-line\", range])\n  endif\n\n  if l:mode == \"add\"\n    let l:tags = []\n    let l:options = []\n\n    if !empty(l:cmd_args)\n      for item in l:cmd_args\n        let splitted = split(item, \",\")\n\n        \" tag only\n        if len(splitted) == 1\n          call add(l:tags, splitted[0])\n        endif\n\n        \" options only\n        if len(splitted) == 2\n          call add(l:tags, splitted[0])\n          call add(l:options, printf(\"%s=%s\", splitted[0], splitted[1]))\n        endif\n      endfor\n    endif\n\n    \" default value\n    if empty(l:tags)\n      let l:tags = [\"json\"]\n    endif\n\n    \" construct tags\n    call extend(cmd, [\"-add-tags\", join(l:tags, \",\")])\n\n      \" construct options\n    if !empty(l:options)\n      call extend(cmd, [\"-add-options\", join(l:options, \",\")])\n    endif\n  elseif l:mode == \"remove\"\n    if empty(l:cmd_args)\n      call add(cmd, \"-clear-tags\")\n    else\n      let l:tags = []\n      let l:options = []\n      for item in l:cmd_args\n        let splitted = split(item, \",\")\n\n        \" tag only\n        if len(splitted) == 1\n          call add(l:tags, splitted[0])\n        endif\n\n        \" options only\n        if len(splitted) == 2\n          call add(l:options, printf(\"%s=%s\", splitted[0], splitted[1]))\n        endif\n      endfor\n\n      \" construct tags\n      if !empty(l:tags)\n        call extend(cmd, [\"-remove-tags\", join(l:tags, \",\")])\n      endif\n\n      \" construct options\n      if !empty(l:options)\n        call extend(cmd, [\"-remove-options\", join(l:options, \",\")])\n      endif\n    endif\n  else\n    return {'err': printf(\"unknown mode: %s\", l:mode)}\n  endif\n\n  return {'cmd': cmd}\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/tags_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunc! TestAddTags() abort\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let l:tmp = gotest#load_fixture('tags/add_all_input.go')\n    silent call go#tags#run(0, 0, 40, \"add\", bufname(''), 1)\n    call gotest#assert_fixture('tags/add_all_golden.go')\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\n\nfunc! TestAddTags_WithOptions() abort\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let l:tmp = gotest#load_fixture('tags/add_all_input.go')\n    silent call go#tags#run(0, 0, 40, \"add\", bufname(''), 1, 'json,omitempty')\n    call gotest#assert_fixture('tags/add_all_golden_options.go')\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! TestAddTags_AddOptions() abort\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let l:tmp = gotest#load_fixture('tags/add_all_input.go')\n    silent call go#tags#run(0, 0, 40, \"add\", bufname(''), 1, 'json')\n    call gotest#assert_fixture('tags/add_all_golden.go')\n    silent call go#tags#run(0, 0, 40, \"add\", bufname(''), 1, 'json,omitempty')\n    call gotest#assert_fixture('tags/add_all_golden_options.go')\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_remove_tags() abort\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let l:tmp = gotest#load_fixture('tags/remove_all_input.go')\n    silent call go#tags#run(0, 0, 40, \"remove\", bufname(''), 1)\n    call gotest#assert_fixture('tags/remove_all_golden.go')\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim:ts=2:sts=2:sw=2:et\n"
  },
  {
    "path": "autoload/go/template.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nlet s:current_file = resolve(expand(\"<sfile>\"))\n\nfunction! go#template#create() abort\n  let l:go_template_use_pkg = go#config#TemplateUsePkg()\n  let l:root_dir = fnamemodify(s:current_file, ':h:h:h')\n\n  let l:package_name = go#tool#PackageName()\n\n  \" if we can't figure out any package name (i.e. no Go files in the directory)\n  \" from the directory create the template or use the directory as the name.\n  if l:package_name == -1\n    if l:go_template_use_pkg == 1\n      let l:path = fnamemodify(expand('%:p:h'), ':t')\n      let l:content = printf(\"package %s\", l:path)\n      call append(0, l:content)\n    else\n      let l:filename = expand('%:t')\n      if l:filename =~ \"_test.go$\"\n        let l:template_file = go#config#TemplateTestFile()\n      else\n        let l:template_file = go#config#TemplateFile()\n      endif\n      \" If template_file is an absolute path, use it as-is. This is to support\n      \" overrides pointing to templates outside of the vim-go plugin dir\n      if fnamemodify(l:template_file, ':p') != l:template_file\n        let l:template_file = go#util#Join(l:root_dir, \"templates\", l:template_file)\n      endif\n\n      silent exe 'keepalt 0r ' . fnameescape(l:template_file)\n    endif\n  else\n    let l:content = printf(\"package %s\", l:package_name)\n    call append(0, l:content)\n  endif\n  \" checking that the last line is empty shouldn't be necessary, but for some\n  \" reason the last line isn't the expected empty line when run via tests.\n  if getline('$') is ''\n    $delete _\n  endif\nendfunction\n\nfunction! go#template#ToggleAutoCreate() abort\n  if go#config#TemplateAutocreate()\n    call go#config#SetTemplateAutocreate(0)\n    call go#util#EchoProgress(\"auto template create disabled\")\n    return\n  end\n\n  call go#config#SetTemplateAutocreate(1)\n  call go#util#EchoProgress(\"auto template create enabled\")\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/template_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunc! Test_TemplateCreate() abort\n  let g:go_gopls_enabled = 0\n  let l:wd = getcwd()\n  try\n    let l:tmp = gotest#write_file('foo/empty.txt', [''])\n\n    edit foo/bar.go\n\n    call gotest#assert_buffer(1, [\n          \\ 'func main() {',\n          \\ '\\tfmt.Println(\"vim-go\")',\n          \\ '}'])\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\n\n  let l:wd = getcwd()\n  try\n    let l:tmp = gotest#write_file('foo/empty.txt', [''])\n    edit foo/bar_test.go\n\n    call gotest#assert_buffer(1, [\n          \\ 'func TestHelloWorld(t *testing.T) {',\n          \\ '\\t// t.Fatal(\"not implemented\")',\n          \\ '}'])\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_TemplateCreate_UsePkg() abort\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let l:tmp = gotest#write_file('foo/empty.txt', [''])\n\n    let g:go_template_use_pkg = 1\n    edit foo/bar.go\n\n    call gotest#assert_buffer(0, ['package foo'])\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_TemplateCreate_PackageExists() abort\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let l:tmp = gotest#write_file('quux/quux.go', ['package foo'])\n\n    edit quux/bar.go\n\n    call gotest#assert_buffer(0, ['package foo'])\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/term.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nlet s:bufnameprefix = 'goterm://'\n\n\" new creates a new terminal with the given command. Mode is set based on the\n\" global variable g:go_term_mode, which is by default set to :vsplit\nfunction! go#term#new(bang, cmd, errorformat) abort\n  return go#term#newmode(a:bang, a:cmd, a:errorformat, go#config#TermMode())\nendfunction\n\n\" go#term#newmode creates a new terminal with the given command and window mode.\nfunction! go#term#newmode(bang, cmd, errorformat, mode) abort\n  let l:mode = a:mode\n  if empty(l:mode)\n    let l:mode = go#config#TermMode()\n  endif\n\n  if go#config#TermReuse()\n    call s:closeterm()\n  endif\n\n  let l:state = {\n        \\ 'cmd': a:cmd,\n        \\ 'bang' : a:bang,\n        \\ 'winid': win_getid(winnr()),\n        \\ 'stdout': [],\n        \\ 'stdout_buf': '',\n        \\ 'errorformat': a:errorformat,\n      \\ }\n\n  \" execute the command in the current file's directory\n  let l:dir = go#util#Chdir(expand('%:p:h'))\n\n  execute l:mode . ' __go_term__'\n  setlocal filetype=goterm\n  setlocal bufhidden=delete\n  setlocal winfixheight\n  \" TODO(bc)?: setlocal winfixwidth\n  setlocal noswapfile\n  setlocal nobuflisted\n\n  \" setup job for nvim\n  if has('nvim')\n    \" explicitly bind callbacks to state so that within them, self will always\n    \" refer to state. See :help Partial for more information.\n    \"\n    \" Don't set an on_stderr, because it will be passed the same data as\n    \" on_stdout. See https://github.com/neovim/neovim/issues/2836\n    let l:job = {\n          \\ 'on_stdout': function('s:on_stdout', [], state),\n          \\ 'on_exit' : function('s:on_exit', [], state),\n        \\ }\n    let l:state.id = termopen(a:cmd, l:job)\n    let l:state.termwinid = win_getid(winnr())\n    let s:lasttermwinid = l:state.termwinid\n    call go#util#Chdir(l:dir)\n\n    \" resize new term if needed.\n    let l:height = go#config#TermHeight()\n    let l:width = go#config#TermWidth()\n\n    \" Adjust the window width or height depending on whether it's a vertical or\n    \" horizontal split.\n    if l:mode =~ \"vertical\" || l:mode =~ \"vsplit\" || l:mode =~ \"vnew\"\n      exe 'vertical resize ' . l:width\n    elseif l:mode =~ \"split\" || l:mode =~ \"new\"\n      exe 'resize ' . l:height\n    endif\n    \" we also need to resize the pty, so there you go...\n    call jobresize(l:state.id, l:width, l:height)\n\n  \" setup term for vim8\n  elseif has('terminal')\n    \" Not great randomness, but \"good enough\" for our purpose here.\n    let l:rnd = sha256(printf('%s%s', reltimestr(reltime()), fnamemodify(bufname(''), \":p\")))\n    let l:termname = printf(\"%s%s\", s:bufnameprefix, l:rnd)\n\n    let l:term = {\n          \\ 'out_cb': function('s:out_cb', [], state),\n          \\ 'exit_cb' : function('s:exit_cb', [], state),\n          \\ 'curwin': 1,\n          \\ 'term_name': l:termname,\n        \\ }\n\n    if l:mode =~ \"vertical\" || l:mode =~ \"vsplit\" || l:mode =~ \"vnew\"\n      let l:term[\"vertical\"] = l:mode\n    endif\n\n    let l:termbufnr = term_start(a:cmd, l:term)\n    let l:state.id = term_getjob(l:termbufnr)\n    let l:state.termwinid = win_getid(bufwinnr(l:termbufnr))\n    let s:lasttermwinid = l:state.termwinid\n    call go#util#Chdir(l:dir)\n\n    \" resize new term if needed.\n    let l:height = go#config#TermHeight()\n    let l:width = go#config#TermWidth()\n\n    \" Adjust the window width or height depending on whether it's a vertical or\n    \" horizontal split.\n    if l:mode =~ \"vertical\" || l:mode =~ \"vsplit\" || l:mode =~ \"vnew\"\n      exe 'vertical resize ' . l:width\n    elseif l:mode =~ \"split\" || l:mode =~ \"new\"\n      exe 'resize ' . l:height\n    endif\n    \"if exists(*term_setsize)\n      \"call term_setsize(l:state.id, l:height, l:width)\n    \"endif\n  endif\n\n  call win_gotoid(l:state.winid)\n  return l:state.id\nendfunction\n\n\" out_cb continually concat's the self.stdout_buf on recv of stdout\n\" and sets self.stdout to the new-lined split content in self.stdout_buf\nfunc! s:out_cb(channel, msg) dict abort\n  let self.stdout_buf = self.stdout_buf . a:msg\n  let self.stdout = split(self.stdout_buf, '\\n')\nendfunction\n\nfunction! s:on_stdout(job_id, data, event) dict abort\n  \" A single empty string means EOF was reached. The first item will never be\n  \" the empty string except for when it's the only item and is signaling that\n  \" EOF was reached.\n  if len(a:data) == 1 && a:data[0] == ''\n    \" when there's nothing buffered, return early so that an\n    \" erroneous message will not be added.\n    if self.stdout_buf == ''\n      return\n    endif\n\n    let self.stdout = add(self.stdout, self.stdout_buf)\n  else\n    let l:data = copy(a:data)\n    let l:data[0] = self.stdout_buf . l:data[0]\n\n    \" The last element may be a partial line; save it for next time.\n    let self.stdout_buf = l:data[-1]\n    let self.stdout = extend(self.stdout, l:data[:-2])\n  endif\nendfunction\n\n\" vim8 exit callback\nfunction! s:exit_cb(job_id, exit_status) dict abort\n  call s:handle_exit(a:job_id, a:exit_status, self)\nendfunction\n\n\" nvim exit callback\nfunction! s:on_exit(job_id, exit_status, event) dict abort\n  call s:handle_exit(a:job_id, a:exit_status, self)\nendfunction\n\n\" handle_exit implements both vim8 and nvim exit callbacks\nfunc s:handle_exit(job_id, exit_status, state) abort\n  let l:winid = win_getid(winnr())\n  call win_gotoid(a:state.winid)\n\n  let l:listtype = go#list#Type(\"_term\")\n\n  if a:exit_status == 0\n    call go#list#Clean(l:listtype)\n    call win_gotoid(l:winid)\n    return\n  endif\n\n  let l:bufdir = expand('%:p:h')\n  if !isdirectory(l:bufdir)\n    call go#util#EchoWarning('terminal job failure not processed, because the job''s working directory no longer exists')\n    call win_gotoid(l:winid)\n    return\n  endif\n\n  \" change to directory where the command was run. If we do not do this the\n  \" quickfix items will have the incorrect paths.\n  \" see: https://github.com/fatih/vim-go/issues/2400\n  let l:dir = go#util#Chdir(l:bufdir)\n\n  let l:title = a:state.cmd\n  if type(l:title) == v:t_list\n    let l:title = join(a:state.cmd)\n  endif\n\n  let l:i = 0\n  while l:i < len(a:state.stdout)\n    let a:state.stdout[l:i] = substitute(a:state.stdout[l:i], \"\\r$\", '', 'g')\n    let l:i += 1\n  endwhile\n\n  call go#list#ParseFormat(l:listtype, a:state.errorformat, a:state.stdout, l:title, 0)\n  let l:errors = go#list#Get(l:listtype)\n  call go#list#Window(l:listtype, len(l:errors))\n\n  \" close terminal; we don't need it anymore\n  if go#config#TermCloseOnExit()\n    call win_gotoid(a:state.termwinid)\n    close!\n  endif\n\n  if empty(l:errors)\n    call go#util#EchoError( '[' . l:title . '] ' . \"FAIL\")\n    call go#util#Chdir(l:dir)\n    call win_gotoid(l:winid)\n    return\n  endif\n\n  if a:state.bang\n    call go#util#Chdir(l:dir)\n    call win_gotoid(l:winid)\n    return\n  endif\n\n  call win_gotoid(a:state.winid)\n  call go#list#JumpToFirst(l:listtype)\n\n  \" change back to original working directory\n  call go#util#Chdir(l:dir)\nendfunction\n\nfunction! go#term#ToggleCloseOnExit() abort\n  if go#config#TermCloseOnExit()\n    call go#config#SetTermCloseOnExit(0)\n    call go#util#EchoProgress(\"term close on exit disabled\")\n    return\n  endif\n\n  call go#config#SetTermCloseOnExit(1)\n  call go#util#EchoProgress(\"term close on exit enabled\")\n  return\nendfunction\n\nfunction! s:closeterm()\n  if !exists('s:lasttermwinid')\n    return\n  endif\n\n  try\n    let l:termwinid = s:lasttermwinid\n    unlet s:lasttermwinid\n    let l:info = getwininfo(l:termwinid)\n    if empty(l:info)\n      return\n    endif\n\n    let l:info = l:info[0]\n\n    if get(l:info, 'terminal', 0) isnot 1\n      return\n    endif\n\n    if has('nvim')\n      if 'goterm' == nvim_buf_get_option(nvim_win_get_buf(l:termwinid), 'filetype')\n        call nvim_win_close(l:termwinid, v:true)\n      endif\n      return\n    endif\n\n    if stridx(bufname(winbufnr(l:termwinid)), s:bufnameprefix, 0) == 0\n      let l:winid = win_getid()\n      call win_gotoid(l:termwinid)\n      close!\n      call win_gotoid(l:winid)\n    endif\n  catch\n    call go#util#EchoError(printf(\"vim-go: %s\", v:exception))\n  endtry\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/term_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunc! Test_GoTermNewMode()\n  if !(has('nvim') || has('terminal'))\n    return\n  endif\n\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let l:filename = 'term/term.go'\n    let l:tmp = gotest#load_fixture(l:filename)\n    call go#util#Chdir(l:tmp . '/src/term')\n\n    let expected = expand('%:p')\n    let l:winid = win_getid()\n\n    let l:expectedwindows = len(getwininfo()) + 1\n\n    let cmd = \"go run \".  go#util#Shelljoin(go#tool#Files())\n\n    set nosplitright\n\n    let l:jobid = go#term#new(0, cmd, &errorformat)\n\n    call go#job#Wait(l:jobid)\n\n    let actual = expand('%:p')\n    call assert_equal(actual, l:expected)\n    call assert_equal(l:expectedwindows, len(getwininfo()))\n\n  finally\n    call win_gotoid(l:winid)\n    only!\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_GoTermNewMode_SplitRight()\n  if !(has('nvim') || has('terminal'))\n    return\n  endif\n\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let l:filename = 'term/term.go'\n    let l:tmp = gotest#load_fixture(l:filename)\n    call go#util#Chdir(l:tmp . '/src/term')\n\n    let expected = expand('%:p')\n    let l:winid = win_getid()\n\n    let l:expectedwindows = len(getwininfo()) + 1\n\n    let cmd = \"go run \".  go#util#Shelljoin(go#tool#Files())\n\n    set splitright\n\n    let l:jobid = go#term#new(0, cmd, &errorformat)\n\n    call go#job#Wait(l:jobid)\n\n    let actual = expand('%:p')\n    call assert_equal(actual, l:expected)\n    call assert_equal(l:expectedwindows, len(getwininfo()))\n\n  finally\n    call win_gotoid(l:winid)\n    only!\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n    set nosplitright\n  endtry\nendfunc\n\nfunc! Test_GoTermReuse()\n  if !(has('nvim') || has('terminal'))\n    return\n  endif\n\n  let l:wd = getcwd()\n  try\n    let g:go_gopls_enabled = 0\n    let l:filename = 'term/term.go'\n    let l:tmp = gotest#load_fixture(l:filename)\n\n    call go#util#Chdir(l:tmp . '/src/term')\n\n    let l:winid = win_getid()\n    let expected = expand('%:p')\n\n    let l:expectedwindows = len(getwininfo())+1\n\n    let cmd = \"go run \".  go#util#Shelljoin(go#tool#Files())\n\n    set nosplitright\n\n    \" prime the terminal window\n    let l:jobid = go#term#new(0, cmd, &errorformat)\n\n    call go#job#Wait(l:jobid)\n\n    let g:go_term_reuse = 1\n\n    let l:jobid = go#term#new(0, cmd, &errorformat)\n\n    call go#job#Wait(l:jobid)\n\n    let actual = expand('%:p')\n    call assert_equal(actual, l:expected)\n    call assert_equal(l:expectedwindows, len(getwininfo()))\n\n    let l:jobid = go#term#new(0, cmd, &errorformat)\n\n    call go#job#Wait(l:jobid)\n\n    let actual = expand('%:p')\n    call assert_equal(actual, l:expected)\n\n    call assert_equal(l:expectedwindows, len(getwininfo()))\n\n  finally\n    call win_gotoid(l:winid)\n    only!\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/test-fixtures/cmd/bad.go",
    "content": "package main\n\nfunc main() {\n\tnotafunc()\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/complete/complete.go",
    "content": "package complete\n\ntype T struct {\n\tV string\n}\n\nfunc Example(s string) {\n\tExample(\"\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/config/buildtags/buildtags.go",
    "content": "package config\n\nfunc Example() {\n\tfoo()\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/config/buildtags/constrainedfoo.go",
    "content": "// +build constrained\n\npackage config\n\n// foo is constrained and this comment exists to make the line numbers different than foo.go\nfunc foo() {\n\tprintln(\"foo\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/config/buildtags/foo.go",
    "content": "// +build !constrained\n\npackage config\n\nfunc foo() {\n\tprintln(\"foo\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/config/buildtags/go.mod",
    "content": "module config\n\ngo 1.13\n"
  },
  {
    "path": "autoload/go/test-fixtures/debug/compilerror/main.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"vim-go\"\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/debug/debugmain/debugmain.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"vim-go\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/def/jump.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"vim-go\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/fmt/hello.go",
    "content": "package main\n\nimport \"fmt\"\n\n  func main() {\nfmt.Println(\"vim-go\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/fmt/hello_golden.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"vim-go\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/fmt/src/imports/goimports.go",
    "content": "package main\nfunc Foo(log *logging.TestLogger) {\n\tlog.Debug(\"vim-go\")\n}\n\nfunc main() {\n\tfmt.Println(\"vim-go\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/fmt/src/imports/goimports_golden.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\n\tlogging \"gh.com/gi/foo-logging\"\n)\n\nfunc Foo(log *logging.TestLogger) {\n\tlog.Debug(\"vim-go\")\n}\n\nfunc main() {\n\tfmt.Println(\"vim-go\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/fmt/src/imports/vendor/gh.com/gi/foo-logging/logger.go",
    "content": "package logging\n\nimport \"fmt\"\n\ntype TestLogger struct {\n\tValue string\n}\n\nfunc (l *TestLogger) Debug(msg string) {\n\tfmt.Println(msg)\n\tfmt.Println(l.Value)\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/job/dir has spaces/main.go",
    "content": "package main\n\nfunc main() {\n\tnotafunc()\n\tprintln(\"vim-go\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lint/src/errcheck/compilererror/compilererror.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"vim-go\"\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lint/src/errcheck/errcheck.go",
    "content": "package errcheck\n\nimport (\n\t\"io\"\n\t\"os\"\n)\n\nfunc foo() {\n\tio.Copy(os.Stdout, os.Stdin)\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lint/src/errcheck/errcheck_test.go",
    "content": "package errcheck\n\nimport (\n\t\"io\"\n\t\"os\"\n\t\"testing\"\n)\n\nfunc TestFoo(t *testing.T) {\n\tio.Copy(os.Stdout, os.Stdin)\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lint/src/errcheck/go.mod",
    "content": "module vim-go.test/errcheck\n\ngo 1.24\n"
  },
  {
    "path": "autoload/go/test-fixtures/lint/src/foo/foo.go",
    "content": "package foo\n\nimport \"fmt\"\n\nfunc MissingFooDoc() {\n\tfmt.Println(\"missing doc\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lint/src/foo/go.mod",
    "content": "module vim-go.test/foo\n\ngo 1.16\n"
  },
  {
    "path": "autoload/go/test-fixtures/lint/src/lint/baz.go",
    "content": "package lint\n\nfunc baz() {}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lint/src/lint/go.mod",
    "content": "module vim-go.test/lint\n\ngo 1.16\n"
  },
  {
    "path": "autoload/go/test-fixtures/lint/src/lint/golangci-lint/problems/importabs/ok.go",
    "content": "package problems\n\nfunc bar() {}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lint/src/lint/golangci-lint/problems/importabs/problems.go",
    "content": "package problems\n\nimport \"/quux\"\n\nfunc baz() {}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lint/src/lint/golangci-lint/problems/multiple/problems.go",
    "content": "package problems\n\nimport (\n\t\"time\"\n)\n\nfunc mySleep(time int) {\n\ttime.Sleep(500 * time.Millisecond)\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lint/src/lint/golangci-lint/problems/shadow/problems.go",
    "content": "package problems\n\nfunc mySleep(time int) {\n\ttime.Sleep(500 * time.Millisecond)\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lint/src/lint/lint.go",
    "content": "package lint\n\nimport \"fmt\"\n\nfunc MissingDoc() {\n\tfmt.Println(\"missing doc\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lint/src/lint/quux.go",
    "content": "package lint\n\nimport \"fmt\"\n\nfunc AlsoMissingDoc() {\n\tfmt.Println(\"missing doc\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lint/src/vet/compilererror/compilererror.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"vim-go\"\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lint/src/vet/go.mod",
    "content": "module vim-go.test/vet\n\ngo 1.16\n"
  },
  {
    "path": "autoload/go/test-fixtures/lint/src/vet/vet.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tstr := \"hello world!\"\n\tfmt.Printf(\"%d\\n\", str)\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lsp/fmt/format.go",
    "content": "package main\n\nimport \"fmt\"\n\n  func main() {\nfmt.Println(\"vim-go\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lsp/fmt/format_golden.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"vim-go\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lsp/fmt/multibyte.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"vim-go\") // 中      asdfasdf\n\tfmt.Println(\"vim-go\") // 中 \n\tfmt.Println(\"vim-go\") // 中a\n\tfmt.Println(\"vim-go\") // 中 \ta\n\tfmt.Println(\"vim-go\") // 中\n\n\tfmt.Println(\"vim-go\") // ⌘      asdfasdf\n\tfmt.Println(\"vim-go\") // ⌘  \n\tfmt.Println(\"vim-go\") // ⌘ a\n\tfmt.Println(\"vim-go\") // ⌘  \ta\n\tfmt.Println(\"vim-go\") // ⌘\n\n\tfmt.Println(\"vim-go\") // é      asdfasdf\n\tfmt.Println(\"vim-go\") // é \n\tfmt.Println(\"vim-go\") // é a\n\tfmt.Println(\"vim-go\") // é  \ta\n\tfmt.Println(\"vim-go\") // é\n\n\n\n\n\n\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lsp/fmt/multibyte_golden.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"vim-go\") // 中      asdfasdf\n\tfmt.Println(\"vim-go\") // 中\n\tfmt.Println(\"vim-go\") // 中a\n\tfmt.Println(\"vim-go\") // 中 \ta\n\tfmt.Println(\"vim-go\") // 中\n\n\tfmt.Println(\"vim-go\") // ⌘      asdfasdf\n\tfmt.Println(\"vim-go\") // ⌘\n\tfmt.Println(\"vim-go\") // ⌘ a\n\tfmt.Println(\"vim-go\") // ⌘  \ta\n\tfmt.Println(\"vim-go\") // ⌘\n\n\tfmt.Println(\"vim-go\") // é      asdfasdf\n\tfmt.Println(\"vim-go\") // é\n\tfmt.Println(\"vim-go\") // é a\n\tfmt.Println(\"vim-go\") // é  \ta\n\tfmt.Println(\"vim-go\") // é\n\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lsp/fmt/newline.go",
    "content": "package main\n\nimport \"fmt\"\nfunc main() {\n\tfmt.Println(\"vim-go\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lsp/imports/imports.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\tio.Copy(ioutil.Discard, os.Stdin)\n\tfmt.Println(\"vim-go\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/lsp/imports/imports_golden.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"os\"\n)\n\nfunc main() {\n\tio.Copy(ioutil.Discard, os.Stdin)\n\tfmt.Println(\"vim-go\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/package/src/package/bar/.gitkeep",
    "content": ""
  },
  {
    "path": "autoload/go/test-fixtures/package/src/package/baz/.gitkeep",
    "content": ""
  },
  {
    "path": "autoload/go/test-fixtures/package/src/package/go.mod",
    "content": "module package\n\ngo 1.12\n"
  },
  {
    "path": "autoload/go/test-fixtures/package/src/package/package.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"vim-go\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/package/src/package/vendor/foo/.gitkeep",
    "content": ""
  },
  {
    "path": "autoload/go/test-fixtures/tags/add_all_golden.go",
    "content": "package main\n\ntype Server struct {\n\tName          string   `json:\"name\"`\n\tID            int      `json:\"id\"`\n\tMyHomeAddress string   `json:\"my_home_address\"`\n\tSubDomains    []string `json:\"sub_domains\"`\n\tEmpty         string   `json:\"empty\"`\n\tExample       int64    `json:\"example\"`\n\tExample2      string   `json:\"example_2\"`\n\tBar           struct {\n\t\tFour string `json:\"four\"`\n\t\tFive string `json:\"five\"`\n\t} `json:\"bar\"`\n\tLala interface{} `json:\"lala\"`\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/tags/add_all_golden_options.go",
    "content": "package main\n\ntype Server struct {\n\tName          string   `json:\"name,omitempty\"`\n\tID            int      `json:\"id,omitempty\"`\n\tMyHomeAddress string   `json:\"my_home_address,omitempty\"`\n\tSubDomains    []string `json:\"sub_domains,omitempty\"`\n\tEmpty         string   `json:\"empty,omitempty\"`\n\tExample       int64    `json:\"example,omitempty\"`\n\tExample2      string   `json:\"example_2,omitempty\"`\n\tBar           struct {\n\t\tFour string `json:\"four,omitempty\"`\n\t\tFive string `json:\"five,omitempty\"`\n\t} `json:\"bar,omitempty\"`\n\tLala interface{} `json:\"lala,omitempty\"`\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/tags/add_all_input.go",
    "content": "package main\n\ntype Server struct {\n\tName          string\n\tID            int\n\tMyHomeAddress string\n\tSubDomains    []string\n\tEmpty         string\n\tExample       int64\n\tExample2      string\n\tBar           struct {\n\t\tFour string\n\t\tFive string\n\t}\n\tLala interface{}\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/tags/remove_all_golden.go",
    "content": "package main\n\ntype Server struct {\n\tName          string   \n\tID            int      \n\tMyHomeAddress string   \n\tSubDomains    []string \n\tEmpty         string   \n\tExample       int64    \n\tExample2      string   \n\tBar           struct {\n\t\tFour string \n\t\tFive string \n\t} \n\tLala interface{} \n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/tags/remove_all_input.go",
    "content": "package main\n\ntype Server struct {\n\tName          string   `json:\"name\"`\n\tID            int      `json:\"id\"`\n\tMyHomeAddress string   `json:\"my_home_address\"`\n\tSubDomains    []string `json:\"sub_domains\"`\n\tEmpty         string   `json:\"empty\"`\n\tExample       int64    `json:\"example\"`\n\tExample2      string   `json:\"example_2\"`\n\tBar           struct {\n\t\tFour string `json:\"four\"`\n\t\tFive string `json:\"five\"`\n\t} `json:\"bar\"`\n\tLala interface{} `json:\"lala\"`\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/term/term.go",
    "content": "package main\n\nfunc main() {\n\tprintln(\"hello, world\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/test/.gitignore",
    "content": "/pkg\n"
  },
  {
    "path": "autoload/go/test-fixtures/test/src/compilerror/compilerror.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"vim-go\"\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/test/src/compilerror/go.mod",
    "content": "module vim-go.test/compilerror\n\ngo 1.16\n"
  },
  {
    "path": "autoload/go/test-fixtures/test/src/example/example.go",
    "content": "package main\n\nfunc HelloWorld() string {\n\treturn \"not the hello you're looking for\"\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/test/src/example/example_test.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc ExampleHelloWorld() {\n\tfmt.Println(\"Hello, World\")\n\t// Output: What's shakin\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/test/src/example/go.mod",
    "content": "module vim-go.test/example\n\ngo 1.24\n"
  },
  {
    "path": "autoload/go/test-fixtures/test/src/play/go.mod",
    "content": "module vim-go.test/play\n\ngo 1.16\n"
  },
  {
    "path": "autoload/go/test-fixtures/test/src/play/mock/controller.go",
    "content": "package mock\n\nimport \"testing\"\n\nfunc Fail(t *testing.T) {\n\tt.Fatal(\"another package badness\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/test/src/play/play_test.go",
    "content": "package play\n\nimport (\n\t\"sync\"\n\t\"testing\"\n\n\t\"vim-go.test/play/mock\"\n)\n\nfunc TestTopSubHelper(t *testing.T) {\n\tt.Run(\"sub\", func(t *testing.T) {\n\t\tt.Log(\"log message\")\n\t\tt.Error(\"sub badness\")\n\t})\n\tt.Error(\"badness\")\n\thelper(t)\n}\n\nfunc TestMultiline(t *testing.T) {\n\tt.Error(\"this is an error\\nand a second line, too\")\n\tt.Error(\"\\nthis is another error\")\n}\n\nfunc TestSub(t *testing.T) {\n\tt.Run(\"indented\", func(t *testing.T) {\n\t\tt.Error(\"this is a sub-test error\\nand a second line, too\")\n\t})\n}\n\nfunc TestOK(t *testing.T) {\n\tt.Run(\"log\", func(t *testing.T) {\n\t\tt.Log(\"goodness\")\n\t})\n}\n\n// TestMocked tests behavior similar to what users may experience when using\n// github.com/golang/mock/gomock.\nfunc TestMocked(t *testing.T) {\n\tmock.Fail(t)\n}\n\nfunc TestPanic(t *testing.T) {\n\tpanic(\"worst ever\")\n}\n\nfunc TestConcurrentPanic(t *testing.T) {\n\tvar wg sync.WaitGroup\n\twg.Add(1)\n\tgo func() {\n\t\tpanic(\"concurrent fail\")\n\t\twg.Done()\n\t}()\n\twg.Wait()\n}\n\nfunc helper(t *testing.T) {\n\tt.Helper()\n\tt.Fatal(\"helper badness\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/test/src/showname/go.mod",
    "content": "module vim-go.test/showname\n\ngo 1.16\n"
  },
  {
    "path": "autoload/go/test-fixtures/test/src/showname/showname_test.go",
    "content": "package main\n\nimport \"testing\"\n\nfunc TestHelloWorld(t *testing.T) {\n\tt.Error(\"so long\")\n\n\tt.Run(\"sub\", func(t *testing.T) {\n\t\tt.Error(\"thanks for all the fish\")\n\t})\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/test/src/testcompilerror/go.mod",
    "content": "module vim-go.test/testcompilerror\n\ngo 1.16\n"
  },
  {
    "path": "autoload/go/test-fixtures/test/src/testcompilerror/testcompilerror_test.go",
    "content": "package main\n\nimport (\n\t\"io/ioutil\"\n\t\"testing\"\n)\n\nfunc TestSomething(t *testing.T) {\n\tr := struct{}{}\n\tioutil.ReadAll(r)\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/test/src/timeout/go.mod",
    "content": "module vim-go.test/timeout\n\ngo 1.16\n"
  },
  {
    "path": "autoload/go/test-fixtures/test/src/timeout/timeout_test.go",
    "content": "// Run a few parallel tests, all in parallel, using multiple techniques for\n// causing the test to take a while so that the stacktraces resulting from a\n// test timeout will contain several goroutines to avoid giving a false sense\n// of confidence or creating error formats that don't account for the more\n// complex scenarios that can occur with timeouts.\n\npackage main\n\nimport (\n\t\"runtime\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc init() {\n\truntime.GOMAXPROCS(3)\n}\n\nfunc TestSleep(t *testing.T) {\n\tt.Parallel()\n\ttime.Sleep(15 * time.Second)\n\tt.Log(\"expected panic if run with timeout < 15s\")\n}\n\nfunc TestRunning(t *testing.T) {\n\tt.Parallel()\n\tc := time.After(15 * time.Second)\nLoop:\n\tfor {\n\t\tselect {\n\t\tcase <-c:\n\t\t\tbreak Loop\n\t\tdefault:\n\t\t}\n\t}\n\n\tt.Log(\"expected panic if run with timeout < 15s\")\n}\n\nfunc TestRunningAlso(t *testing.T) {\n\tt.Parallel()\n\tc := time.After(15 * time.Second)\nLoop:\n\tfor {\n\t\tselect {\n\t\tcase <-c:\n\t\t\tbreak Loop\n\t\tdefault:\n\t\t}\n\t}\n\tt.Log(\"expected panic if run with timeout < 15s\")\n}\n"
  },
  {
    "path": "autoload/go/test-fixtures/test/src/veterror/go.mod",
    "content": "module vim-go.test/veterror\n\ngo 1.16\n"
  },
  {
    "path": "autoload/go/test-fixtures/test/src/veterror/veterror.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Errorf(\"%v\")\n}\n"
  },
  {
    "path": "autoload/go/test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\n\" Test runs `go test` in the current directory. If compile is true, it'll\n\" compile the tests instead of running them (useful to catch errors in the\n\" test files). Any other argument is appended to the final `go test` command.\nfunction! go#test#Test(bang, compile, ...) abort\n  let args = [\"test\"]\n  if len(go#config#BuildTags()) > 0\n    call extend(args, [\"-tags\", go#config#BuildTags()])\n  endif\n\n  \" don't run the test, only compile it. Useful to capture and fix errors.\n  if a:compile\n    let testfile = tempname() . \".vim-go.test\"\n    call extend(args, [\"-c\", \"-o\", testfile])\n  endif\n\n  if a:0\n    let goargs = a:000\n\n    \" do not expand for coverage mode as we're passing the arg ourself\n    if a:1 != '-coverprofile'\n      \" expand all wildcards(i.e: '%' to the current file name)\n      let goargs = map(copy(a:000), \"expand(v:val)\")\n    endif\n\n    call extend(args, goargs, 1)\n  else\n    \" only add this if no custom flags are passed\n    let timeout = go#config#TestTimeout()\n    call add(args, printf(\"-timeout=%s\", timeout))\n  endif\n\n  if go#config#TermEnabled()\n    call go#term#new(a:bang, [\"go\"] + args, s:errorformat())\n    return\n  endif\n\n  if go#util#has_job()\n    \" use vim's job functionality to call it asynchronously\n    let job_options  = {\n          \\ 'bang': a:bang,\n          \\ 'for': 'GoTest',\n          \\ 'statustype': 'test',\n          \\ 'errorformat': s:errorformat(),\n          \\ }\n\n    if a:compile\n      let job_options.statustype = 'compile ' . job_options.statustype\n    endif\n\n    call s:test_job(['go'] + args, job_options)\n    return\n  endif\n\n  if go#config#EchoCommandInfo()\n    if a:compile\n      call go#util#EchoProgress(\"compiling tests ...\")\n    else\n      call go#util#EchoProgress(\"testing...\")\n    endif\n  endif\n\n  call go#cmd#autowrite()\n  redraw\n\n  let l:cmd = ['go'] + l:args\n\n  let [l:out, l:err] = go#util#ExecInDir(l:cmd)\n  \" TODO(bc): When the output is JSON, the JSON should be run through a\n  \" filter to produce lines that are more easily described by errorformat.\n\n  let l:listtype = go#list#Type(\"GoTest\")\n\n  let l:dir = go#util#Chdir(expand(\"%:p:h\"))\n\n  if l:err != 0\n    let l:winid = win_getid(winnr())\n    call go#list#ParseFormat(l:listtype, s:errorformat(), split(out, '\\n'), l:cmd, 0)\n    let errors = go#list#Get(l:listtype)\n    call go#list#Window(l:listtype, len(errors))\n    if empty(errors)\n      \" failed to parse errors, output the original content\n      call go#util#EchoError(out)\n    elseif a:bang\n      call win_gotoid(l:winid)\n    else\n      call go#list#JumpToFirst(l:listtype)\n    endif\n  else\n    call go#list#Clean(l:listtype)\n\n    if a:compile\n      call go#util#EchoSuccess(\"[test] SUCCESS\")\n    else\n      call go#util#EchoSuccess(\"[test] PASS\")\n    endif\n  endif\n  call go#util#Chdir(l:dir)\nendfunction\n\n\" go#test#Func runs a single test that surrounds the current cursor position.\n\" Arguments are passed to the `go test` command.\nfunction! go#test#Func(bang, ...) abort\n  let l:test = go#util#TestName()\n  if l:test is ''\n    call go#util#EchoWarning(\"[test] no test found immediate to cursor\")\n    return\n  endif\n  let args = [a:bang, 0, \"-run\", printf('^%s$', l:test)]\n\n  if a:0\n    call extend(args, a:000)\n  else\n    \" only add this if no custom flags are passed\n    let timeout = go#config#TestTimeout()\n    call add(args, printf(\"-timeout=%s\", timeout))\n  endif\n\n  call call('go#test#Test', args)\nendfunction\n\n\" go#test#File runs all the tests in the current file.\n\" Arguments are passed to the `go test` command.\nfunction! go#test#File(bang, ...) abort\n  let l:tests = go#util#TestNamesInFile()\n  if len(l:tests) is 0\n    call go#util#EchoWarning(\"[test] no tests found\")\n    return\n  endif\n\n  let args = [a:bang, 0, \"-run\", printf('^Test(%s)$', join(map(l:tests, 'substitute(v:val, \"^Test\", \"\", \"\")'), '|'))]\n\n  if a:0\n    call extend(args, a:000)\n  else\n    \" only add this if no custom flags are passed\n    let timeout = go#config#TestTimeout()\n    call add(args, printf(\"-timeout=%s\", timeout))\n  endif\n\n  call call('go#test#Test', args)\nendfunction\n\nfunction! s:test_job(cmd, args) abort\n  \" autowrite is not enabled for jobs\n  call go#cmd#autowrite()\n\n  call go#job#Spawn(a:cmd, a:args)\nendfunction\n\nlet s:efm = \"\"\nlet s:go_test_show_name = 0\n\nfunction! s:errorformat() abort\n  \" NOTE(arslan): once we get JSON output everything will be easier :).\n  \" TODO(bc): When the output is JSON, the JSON should be run through a\n  \" filter to produce lines that are more easily described by errorformat.\n  \"   https://github.com/golang/go/issues/2981.\n  let goroot = go#util#goroot()\n\n  let show_name = go#config#TestShowName()\n  if s:efm != \"\" && s:go_test_show_name == show_name\n    return s:efm\n  endif\n  let s:go_test_show_name = show_name\n\n  \" each level of test indents the test output 4 spaces. Capturing groups\n  \" (e.g. \\(\\)) cannot be used in an errorformat, but non-capturing groups can\n  \" (e.g. \\%(\\)).\n  let indent = '%\\\\%(    %\\\\)'\n\n  \" ignore `go test -v` output for starting tests\n  let format = \"%-G=== RUN   %.%#\"\n  \" ignore `go test -v` output for passing tests\n  let format .= \",%-G\" . indent . \"%#--- PASS: %.%#\"\n\n  \" Match failure lines.\n\n  \" Example failures start with '--- FAIL: ', followed by the example name\n  \" followed by a space , followed by the duration of the example in\n  \" parantheses. They aren't nested, though, so don't check for indentation.\n  \" The errors from them also aren't indented and don't report file location\n  \" or line numbers, so those won't show up. This will at least let the user\n  \" know which example failed, though.\n  let format .= ',%G--- FAIL: %\\\\%(Example%\\\\)%\\\\@=%m (%.%#)'\n\n  \" Test failures start with '--- FAIL: ', followed by the test name followed\n  \" by a space, followed by the duration of the test in parentheses.\n  \"\n  \" e.g.:\n  \"   '--- FAIL: TestSomething (0.00s)'\n  if show_name\n    let format .= \",%G\" . indent . \"%#--- FAIL: %m (%.%#)\"\n  else\n    let format .= \",%-G\" . indent . \"%#--- FAIL: %.%#\"\n  endif\n\n  \" Go 1.10 test output {{{1\n  \" Matches test output lines.\n  \"\n  \" All test output lines start with the test indentation and a tab, followed\n  \" by the filename, a colon, the line number, another colon, a space, and the\n  \" message. e.g.:\n  \"   '\\ttime_test.go:30: Likely problem: the time zone files have not been installed.'\n  let format .= \",%A\" . indent . \"%#%\\\\t%\\\\+%f:%l: %m\"\n  \" also match lines that don't have a message (i.e. the message begins with a\n  \" newline or is the empty string):\n  \" e.g.:\n  \"     t.Errorf(\"\\ngot %v; want %v\", actual, expected)\n  \"     t.Error(\"\")\n  let format .= \",%A\" . indent . \"%#%\\\\t%\\\\+%f:%l: \"\n\n  \" Match the 2nd and later lines of multi-line output. These lines are\n  \" indented the number of spaces for the level of nesting of the test,\n  \" followed by two tabs, followed by the message.\n  \"\n  \" Treat these lines as if they are stand-alone lines of output by using %G.\n  \" It would also be valid to treat these lines as if they were the\n  \" continuation of a multi-line error by using %C instead of %G, but that\n  \" would also require that all test errors using a %A or %E modifier to\n  \" indicate that they're multiple lines of output, but in that case the lines\n  \" get concatenated in the quickfix list, which is not what users typically\n  \" want when writing a newline into their test output.\n  let format .= \",%G\" . indent . \"%#%\\\\t%\\\\{2}%m\"\n  \" }}}1\n\n  \" Go 1.14 test verbose output {{{1\n  \" Match test output lines similarly to Go 1.11 test output lines, but they\n  \" have the test name followed by a colon before the filename when run with\n  \" the -v flag.\n  let format .= \",%A\" . indent . \"%\\\\+%[%^:]%\\\\+: %f:%l: %m\"\n  let format .= \",%A\" . indent . \"%\\\\+%[%^:]%\\\\+: %f:%l: \"\n  \" }}}1\n\n  \" Go 1.11 test output {{{1\n  \" Match test output lines similarly to Go 1.10 test output lines, but they\n  \" use an indent level where the Go 1.10 test output uses tabs, so they'll\n  \" always have at least one level indentation...\n  let format .= \",%A\" . indent . \"%\\\\+%f:%l: %m\"\n  let format .= \",%A\" . indent . \"%\\\\+%f:%l: \"\n  let format .= \",%G\" . indent . \"%\\\\{2\\\\,}%m\"\n  \" }}}1\n\n  \" set the format for panics.\n\n  \" handle panics from test timeouts\n  let format .= \",%+Gpanic: test timed out after %.%\\\\+\"\n  \" Go 1.20 started adding a list of the running tests when a timeout occurs\n  let format .= \",%+Grunning tests:\"\n\n  \" handle non-timeout panics\n  \" In addition to 'panic', check for 'fatal error' to support older versions\n  \" of Go that used 'fatal error'.\n  \"\n  \" Panics come in two flavors. When the goroutine running the tests panics,\n  \" `go test` recovers and tries to exit more cleanly. In that case, the panic\n  \" message is suffixed with ' [recovered]'. If the panic occurs in a\n  \" different goroutine, it will not be suffixed with ' [recovered]'.\n  let format .= \",%+Afatal error: %.%# [recovered]\"\n  let format .= \",%+Apanic: %.%# [recovered]\"\n  let format .= \",%+Afatal error: %.%#\"\n  let format .= \",%+Apanic: %.%#\"\n\n  \" Match address lines in stacktraces produced by panic.\n  \"\n  \" Address lines in the stack trace have leading tabs, followed by the path\n  \" to the file. The file path is followed by a colon and then the line number\n  \" within the file where the panic occurred. After that there's a space and\n  \" hexadecimal number.\n  \"\n  \" e.g.:\n  \"   '\\t/usr/local/go/src/time.go:1313 +0x5d'\n\n  \" panicaddress and readyaddress are identical except for\n  \" panicaddress sets the filename and line number.\n  let panicaddress = \"%\\\\t%f:%l +0x%[0-9A-Fa-f]%\\\\+\"\n  let readyaddress = \"%\\\\t%\\\\f%\\\\+:%\\\\d%\\\\+ +0x%[0-9A-Fa-f]%\\\\+\"\n  \" stdlib address is identical to readyaddress, except it matches files\n  \" inside GOROOT.\n  let stdlibaddress = \"%\\\\t\" . goroot . \"%\\\\f%\\\\+:%\\\\d%\\\\+ +0x%[0-9A-Fa-f]%\\\\+\"\n\n  \" Match and ignore the running goroutine line.\n  let format .= \",%-Cgoroutine %\\\\d%\\\\+ [running]:\"\n  \" Match address lines that refer to stdlib, but consider them informational\n  \" only. This is to catch the lines after the first address line in the\n  \" running goroutine of a panic stack trace. Ideally, this wouldn't be\n  \" necessary, but when a panic happens in the goroutine running a test, it's\n  \" recovered and another panic is created, so the stack trace actually has\n  \" the line that caused the original panic a couple of addresses down the\n  \" stack.\n  let format .= \",%-C\" . stdlibaddress\n  \" Match address lines in the first matching goroutine. This means the panic\n  \" message will only be shown as the error message in the first address of\n  \" the running goroutine's stack.\n  let format .= \",%Z\" . panicaddress\n\n  \" Match and ignore errors from runtime.goparkunlock(). These started\n  \" appearing in stack traces from Go 1.12 test timeouts.\n  let format .= \",%-Gruntime.goparkunlock(%.%#\"\n  let format .= \",%-G%\\\\t\" . goroot . \"%\\\\f%\\\\+:%\\\\d%\\\\+\"\n\n  \" Match and ignore panic address without being part of a multi-line message.\n  \" This is to catch those lines that come after the top most non-standard\n  \" library line in stack traces.\n  let format .= \",%-G\" . readyaddress\n\n  \" Match and ignore exit status lines (produced when go test panics) whether\n  \" part of a multi-line message or not, because these lines sometimes come\n  \" before and sometimes after panic stacktraces.\n  let format .= \",%-Cexit status %[0-9]%\\\\+\"\n  \"let format .= \",exit status %[0-9]%\\\\+\"\n\n  \" Match and ignore failure lines whether part of a multi-line message\n  \" or not, because these lines sometimes come before and sometimes after\n  \" panic stacktraces.\n  let format .= \",%-CFAIL%\\\\t%.%#\"\n  \"let format .= \",FAIL%\\\\t%.%#\"\n\n  \" match compiler errors.\n  \" These are very smilar to errors from <=go1.10 test output, but lack\n  \" leading tabs for the first line of an error, and subsequent lines only\n  \" have one tab instead of two.\n  let format .= \",%A%f:%l:%c: %m\"\n  let format .= \",%A%f:%l: %m\"\n  \" It would be nice if this weren't necessary, but panic lines from tests are\n  \" prefixed with a single leading tab, making them very similar to 2nd and\n  \" later lines of a multi-line compiler error. Swallow it so that it doesn't\n  \" cause a quickfix entry since the next %G entry can add a quickfix entry\n  \" for 2nd and later lines of a multi-line compiler error.\n  let format .= \",%-C%\\\\tpanic: %.%#\"\n  let format .= \",%G%\\\\t%m\"\n\n  \" Match and ignore everything else in multi-line messages.\n  let format .= \",%-C%.%#\"\n  \" Match and ignore everything else not in a multi-line message:\n  let format .= \",%-G%.%#\"\n\n  let s:efm = format\n\n  return s:efm\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/test_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunc! Test_GoTest() abort\n  let expected = [\n        \\ {'lnum': 12, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'log message'},\n        \\ {'lnum': 13, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'sub badness'},\n        \\ {'lnum': 15, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'badness'},\n        \\ {'lnum': 16, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'helper badness'},\n        \\ {'lnum': 20, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is an error'},\n        \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'and a second line, too'},\n        \\ {'lnum': 21, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': ''},\n        \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is another error'},\n        \\ {'lnum': 26, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is a sub-test error'},\n        \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'and a second line, too'},\n        \\ {'lnum': 6, 'bufnr': 3, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'another package badness'},\n        \\ {'lnum': 43, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'panic: worst ever [recovered, repanicked]'}\n      \\ ]\n  let [l:goversion, l:err] = go#util#Exec(['go', 'env', 'GOVERSION'])\n  let l:goversion = split(l:goversion, \"\\n\")[0]\n  if l:goversion < 'go1.25'\n    let expected = [\n        \\ {'lnum': 12, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'log message'},\n        \\ {'lnum': 13, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'sub badness'},\n        \\ {'lnum': 15, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'badness'},\n        \\ {'lnum': 16, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'helper badness'},\n        \\ {'lnum': 20, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is an error'},\n        \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'and a second line, too'},\n        \\ {'lnum': 21, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': ''},\n        \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is another error'},\n        \\ {'lnum': 26, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is a sub-test error'},\n        \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'and a second line, too'},\n        \\ {'lnum': 6, 'bufnr': 3, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'another package badness'},\n        \\ {'lnum': 43, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'panic: worst ever [recovered]'}\n      \\ ]\n  endif\n  call s:test('play/play_test.go', expected)\nendfunc\n\nfunc! Test_GoTestConcurrentPanic()\n  let expected = [\n        \\ {'lnum': 50, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'panic: concurrent fail'}\n      \\ ]\n  call s:test('play/play_test.go', expected, \"-run\", \"TestConcurrentPanic\")\nendfunc\n\nfunc! Test_GoTestVerbose() abort\n  let expected = [\n        \\ {'lnum': 12, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'log message'},\n        \\ {'lnum': 13, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'sub badness'},\n        \\ {'lnum': 15, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'badness'},\n        \\ {'lnum': 16, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'helper badness'},\n        \\ {'lnum': 20, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is an error'},\n        \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'and a second line, too'},\n        \\ {'lnum': 21, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': ''},\n        \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is another error'},\n        \\ {'lnum': 26, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is a sub-test error'},\n        \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'and a second line, too'},\n        \\ {'lnum': 32, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'goodness'},\n        \\ {'lnum': 6, 'bufnr': 3, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'another package badness'},\n        \\ {'lnum': 43, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'panic: worst ever [recovered, repanicked]'}\n      \\ ]\n  let [l:goversion, l:err] = go#util#Exec(['go', 'env', 'GOVERSION'])\n  let l:goversion = split(l:goversion, \"\\n\")[0]\n  if l:goversion < 'go1.25'\n    let expected = [\n          \\ {'lnum': 12, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'log message'},\n          \\ {'lnum': 13, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'sub badness'},\n          \\ {'lnum': 15, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'badness'},\n          \\ {'lnum': 16, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'helper badness'},\n          \\ {'lnum': 20, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is an error'},\n          \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'and a second line, too'},\n          \\ {'lnum': 21, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': ''},\n          \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is another error'},\n          \\ {'lnum': 26, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is a sub-test error'},\n          \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'and a second line, too'},\n          \\ {'lnum': 32, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'goodness'},\n          \\ {'lnum': 6, 'bufnr': 3, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'another package badness'},\n          \\ {'lnum': 43, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'panic: worst ever [recovered]'}\n        \\ ]\n  endif\n  call s:test('play/play_test.go', expected, \"-v\")\nendfunc\n\nfunc! Test_GoTestCompilerError() abort\n  let expected = [\n        \\ {'lnum': 6, 'bufnr': 6, 'col': 22, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'syntax error: unexpected newline in argument list; possibly missing comma or )'}\n      \\ ]\n\n  call s:test('compilerror/compilerror_test.go', expected)\nendfunc\n\nfunc! Test_GoTestTimeout() abort\n  let expected = [\n        \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'panic: test timed out after 500ms'},\n        \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'running tests:'},\n        \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'TestRunning (0.000s)'},\n        \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'TestRunningAlso (0.000s)'},\n        \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'TestSleep (0.000s)'},\n      \\ ]\n\n  let [l:goversion, l:err] = go#util#Exec(['go', 'env', 'GOVERSION'])\n  let l:goversion = split(l:goversion, \"\\n\")[0]\n  if l:goversion < 'go1.20'\n    let expected = [\n          \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'panic: test timed out after 500ms'},\n        \\ ]\n  endif\n\n  let g:go_test_timeout=\"500ms\"\n  call s:test('timeout/timeout_test.go', expected)\nendfunc\n\nfunc! Test_GoTestShowName() abort\n  let expected = [\n        \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'TestHelloWorld'},\n        \\ {'lnum': 6, 'bufnr': 8, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'so long'},\n        \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'TestHelloWorld/sub'},\n        \\ {'lnum': 9, 'bufnr': 8, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'thanks for all the fish'},\n      \\ ]\n\n  let g:go_test_show_name=1\n  call s:test('showname/showname_test.go', expected)\nendfunc\n\nfunc! Test_GoTestVet() abort\n  let expected = [\n        \\ {'lnum': 6, 'bufnr': 11, 'col': 14, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'fmt.Errorf format %v reads arg #1, but call has 0 args'},\n      \\ ]\n\n  let [l:goversion, l:err] = go#util#Exec(['go', 'env', 'GOVERSION'])\n  let l:goversion = split(l:goversion, \"\\n\")[0]\n  if l:goversion < 'go1.25'\n    let expected = [\n          \\ {'lnum': 6, 'bufnr': 11, 'col': 2, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'fmt.Errorf format %v reads arg #1, but call has 0 args'},\n        \\ ]\n  endif\n\n  call s:test('veterror/veterror.go', expected)\nendfunc\n\nfunc! Test_GoTestTestCompilerError() abort\n  let expected = [\n        \\ {'lnum': 10, 'bufnr': 9, 'col': 17, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'cannot use r (variable of type struct{}) as io.Reader value in argument to ioutil.ReadAll: struct{} does not implement io.Reader (missing method Read)'},\n      \\ ]\n\n  let [l:goversion, l:err] = go#util#Exec(['go', 'env', 'GOVERSION'])\n  let l:goversion = split(l:goversion, \"\\n\")[0]\n\n  call s:test('testcompilerror/testcompilerror_test.go', expected)\nendfunc\n\nfunc! Test_GoTestExample() abort\n  let expected = [\n        \\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'ExampleHelloWorld'}\n      \\ ]\n  call s:test('example/example_test.go', expected)\nendfunc\n\nfunc! s:test(file, expected, ...) abort\n  let g:go_gopls_enabled = 0\n  let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/test'\n  call go#util#Chdir(printf('%s/src/%s', $GOPATH, fnamemodify(a:file, ':h')))\n  silent exe 'e ' . $GOPATH . '/src/' . a:file\n\n  \" clear the quickfix lists\n  call setqflist([], 'r')\n\n  let args = [1,0]\n  if a:0\n    let args += a:000\n  endif\n\n  \" run the tests\n  silent call call(function('go#test#Test'), args)\n\n  let actual = getqflist()\n  let start = reltime()\n  while len(actual) == 0 && reltimefloat(reltime(start)) < 10\n    sleep 100m\n    let actual = getqflist()\n  endwhile\n\n  for item in actual\n    let item.text = s:normalize_durations(item.text)\n  endfor\n\n  for item in a:expected\n    let item.text = s:normalize_durations(item.text)\n  endfor\n\n  call gotest#assert_quickfix(actual, a:expected)\nendfunc\n\nfunc! s:normalize_durations(str) abort\n  return substitute(a:str, '[0-9]\\+\\(\\.[0-9]\\+\\)\\?s', '0.000s', 'g')\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/textobj.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\n\" ( ) motions\n\" { } motions\n\" s for sentence\n\" p for paragraph\n\" < >\n\" t for tag\n\nfunction! go#textobj#Comment(mode) abort\n  let l:fname = expand('%:p')\n\n  try\n    if &modified\n      let l:tmpname = tempname()\n      call writefile(go#util#GetLines(), l:tmpname)\n      let l:fname = l:tmpname\n    endif\n\n    let l:cmd = ['motion',\n          \\ '-format', 'json',\n          \\ '-file', l:fname,\n          \\ '-offset', go#util#OffsetCursor(),\n          \\ '-mode', 'comment',\n          \\ ]\n\n    let [l:out, l:err] = go#util#Exec(l:cmd)\n    if l:err\n      call go#util#EchoError(l:out)\n      return\n    endif\n  finally\n    if exists(\"l:tmpname\")\n      call delete(l:tmpname)\n    endif\n  endtry\n\n  let l:result = json_decode(l:out)\n  if type(l:result) != 4 || !has_key(l:result, 'comment')\n    return\n  endif\n\n  let l:info = l:result.comment\n  call cursor(l:info.startLine, l:info.startCol)\n\n  \" Adjust cursor to exclude start comment markers. Try to be a little bit\n  \" clever when using multi-line '/*' markers.\n  if a:mode is# 'i'\n    \" trim whitespace so matching below works correctly\n    let l:line = substitute(getline('.'), '^\\s*\\(.\\{-}\\)\\s*$', '\\1', '')\n\n    \" //text\n    if l:line[:2] is# '// '\n      call cursor(l:info.startLine, l:info.startCol+3)\n    \" // text\n    elseif l:line[:1] is# '//'\n      call cursor(l:info.startLine, l:info.startCol+2)\n    \" /*\n    \" text\n    elseif l:line =~# '^/\\* *$'\n      call cursor(l:info.startLine+1, 0)\n      \" /*\n      \"  * text\n      if getline('.')[:2] is# ' * '\n        call cursor(l:info.startLine+1, 4)\n      \" /*\n      \"  *text\n      elseif getline('.')[:1] is# ' *'\n        call cursor(l:info.startLine+1, 3)\n      endif\n    \" /* text\n    elseif l:line[:2] is# '/* '\n      call cursor(l:info.startLine, l:info.startCol+3)\n    \" /*text\n    elseif l:line[:1] is# '/*'\n      call cursor(l:info.startLine, l:info.startCol+2)\n    endif\n  endif\n\n  normal! v\n\n  \" Exclude trailing newline.\n  if a:mode is# 'i'\n    let l:info.endCol -= 1\n  endif\n\n  call cursor(l:info.endLine, l:info.endCol)\n\n  \" Exclude trailing '*/'.\n  if a:mode is# 'i'\n    let l:line = getline('.')\n    \" text\n    \" */\n    if l:line =~# '^ *\\*/$'\n      call cursor(l:info.endLine - 1, len(getline(l:info.endLine - 1)))\n    \" text */\n    elseif l:line[-3:] is# ' */'\n      call cursor(l:info.endLine, l:info.endCol - 3)\n    \" text*/\n    elseif l:line[-2:] is# '*/'\n      call cursor(l:info.endLine, l:info.endCol - 2)\n    endif\n  endif\nendfunction\n\n\" Select a function in visual mode.\nfunction! go#textobj#Function(mode) abort\n  let l:fname = expand(\"%:p\")\n  if &modified\n    let l:tmpname = tempname()\n    call writefile(go#util#GetLines(), l:tmpname)\n    let l:fname = l:tmpname\n  endif\n\n  let l:cmd = ['motion',\n        \\ '-format', 'vim',\n        \\ '-file', l:fname,\n        \\ '-offset', go#util#OffsetCursor(),\n        \\ '-mode', 'enclosing',\n        \\ ]\n\n  if go#config#TextobjIncludeFunctionDoc()\n    let l:cmd += ['-parse-comments']\n  endif\n\n  let [l:out, l:err] = go#util#Exec(l:cmd)\n  if l:err\n    call go#util#EchoError(out)\n    return\n  endif\n\n  \" if exists, delete it as we don't need it anymore\n  if exists(\"l:tmpname\")\n    call delete(l:tmpname)\n  endif\n\n  \" convert our string dict representation into native Vim dictionary type\n  let result = eval(out)\n  if type(result) != 4 || !has_key(result, 'fn')\n    return\n  endif\n\n  let info = result.fn\n\n  if a:mode == 'a'\n    \" anonymous functions doesn't have associated doc. Also check if the user\n    \" want's to include doc comments for function declarations\n    if has_key(info, 'doc') && go#config#TextobjIncludeFunctionDoc()\n      call cursor(info.doc.line, info.doc.col)\n    elseif info['sig']['name'] == '' && go#config#TextobjIncludeVariable()\n      \" one liner anonymous functions\n      if info.lbrace.line == info.rbrace.line\n        \" jump to first nonblack char, to get the correct column\n        call cursor(info.lbrace.line, 0 )\n        normal! ^\n        call cursor(info.func.line, col(\".\"))\n      else\n        call cursor(info.func.line, info.rbrace.col)\n      endif\n    else\n      call cursor(info.func.line, info.func.col)\n    endif\n\n    normal! v\n    call cursor(info.rbrace.line, info.rbrace.col)\n    return\n  endif\n\n  \" rest is inner mode, a:mode == 'i'\n\n  \" if the function is a one liner we need to select only that portion\n  if info.lbrace.line == info.rbrace.line\n    call cursor(info.lbrace.line, info.lbrace.col+1)\n    normal! v\n    call cursor(info.rbrace.line, info.rbrace.col-1)\n    return\n  endif\n\n  call cursor(info.lbrace.line+1, 1)\n  normal! V\n  call cursor(info.rbrace.line-1, 1)\nendfunction\n\n\" Get the location of the previous or next function.\nfunction! go#textobj#FunctionLocation(direction, cnt) abort\n  let l:fname = expand(\"%:p\")\n  if &modified\n    \" Write current unsaved buffer to a temp file and use the modified content\n    let l:tmpname = tempname()\n    call writefile(go#util#GetLines(), l:tmpname)\n    let l:fname = l:tmpname\n  endif\n\n  let l:cmd = ['motion',\n        \\ '-format', 'vim',\n        \\ '-file', l:fname,\n        \\ '-offset', go#util#OffsetCursor(),\n        \\ '-shift', a:cnt,\n        \\ '-mode', a:direction,\n        \\ ]\n\n  if go#config#TextobjIncludeFunctionDoc()\n    let l:cmd += ['-parse-comments']\n  endif\n\n  let [l:out, l:err] = go#util#Exec(l:cmd)\n  if l:err\n    call go#util#EchoError(out)\n    return\n  endif\n\n  \" if exists, delete it as we don't need it anymore\n  if exists(\"l:tmpname\")\n    call delete(l:tmpname)\n  endif\n\n  let l:result = json_decode(out)\n  if type(l:result) != 4 || !has_key(l:result, 'fn')\n    return 0\n  endif\n\n  return l:result\nendfunction\n\nfunction! go#textobj#FunctionJump(mode, direction) abort\n  \" get count of the motion. This should be done before all the normal\n  \" expressions below as those reset this value(because they have zero\n  \" count!). We abstract -1 because the index starts from 0 in motion.\n  let l:cnt = v:count1 - 1\n\n  \" set context mark so we can jump back with  '' or ``\n  normal! m'\n\n  \" select already previously selected visual content and continue from there.\n  \" If it's the first time starts with the visual mode. This is needed so\n  \" after selecting something in visual mode, every consecutive motion\n  \" continues.\n  if a:mode == 'v'\n    normal! gv\n  endif\n\n  let l:result = go#textobj#FunctionLocation(a:direction, l:cnt)\n  if l:result is 0\n    return\n  endif\n\n  \" we reached the end and there are no functions. The usual [[ or ]] jumps to\n  \" the top or bottom, we'll do the same.\n  if type(result) == 4 && has_key(result, 'err') && result.err == \"no functions found\"\n    if a:direction == 'next'\n      keepjumps normal! G\n    else \" 'prev'\n      keepjumps normal! gg\n    endif\n    return\n  endif\n\n  let info = result.fn\n\n  \" if we select something ,select all function\n  if a:mode == 'v' && a:direction == 'next'\n    keepjumps call cursor(info.rbrace.line, 1)\n    return\n  endif\n\n  if a:mode == 'v' && a:direction == 'prev'\n    if has_key(info, 'doc') && go#config#TextobjIncludeFunctionDoc()\n      keepjumps call cursor(info.doc.line, 1)\n    else\n      keepjumps call cursor(info.func.line, 1)\n    endif\n    return\n  endif\n\n  keepjumps call cursor(info.func.line, 1)\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/tool.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\n\" From \"go list -h\".\nfunction! go#tool#ValidFiles(...)\n  let l:list = [\"GoFiles\", \"CgoFiles\", \"IgnoredGoFiles\", \"CFiles\", \"CXXFiles\",\n    \\ \"MFiles\", \"HFiles\", \"FFiles\", \"SFiles\", \"SwigFiles\", \"SwigCXXFiles\",\n    \\ \"SysoFiles\", \"TestGoFiles\", \"XTestGoFiles\"]\n\n  \" Used as completion\n  if len(a:000) > 0\n    let l:list = filter(l:list, 'strpart(v:val, 0, len(a:1)) == a:1')\n  endif\n\n  return l:list\nendfunction\n\nfunction! go#tool#Files(...) abort\n  if len(a:000) > 0\n    let source_files = a:000\n  else\n    let source_files = ['GoFiles']\n  endif\n\n  let combined = ''\n  for sf in source_files\n    \" Strip dot in case people used \":GoFiles .GoFiles\".\n    let sf = substitute(sf, '^\\.', '', '')\n\n    \" Make sure the passed options are valid.\n    if index(go#tool#ValidFiles(), sf) == -1\n      echoerr \"unknown source file variable: \" . sf\n    endif\n\n    if go#util#IsWin()\n      let combined .= '{{range $f := .' . sf . '}}{{$.Dir}}\\{{$f}}{{printf \\\"\\n\\\"}}{{end}}{{range $f := .CgoFiles}}{{$.Dir}}\\{{$f}}{{printf \\\"\\n\\\"}}{{end}}'\n    else\n      let combined .= \"{{range $f := .\" . sf . \"}}{{$.Dir}}/{{$f}}{{printf \\\"\\\\n\\\"}}{{end}}{{range $f := .CgoFiles}}{{$.Dir}}/{{$f}}{{printf \\\"\\\\n\\\"}}{{end}}\"\n    endif\n  endfor\n\n  let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', l:combined])\n  return split(l:out, '\\n')\nendfunction\n\nfunction! go#tool#Deps() abort\n  if go#util#IsWin()\n    let format = '{{range $f := .Deps}}{{$f}}{{printf \\\"\\n\\\"}}{{end}}'\n  else\n    let format = \"{{range $f := .Deps}}{{$f}}\\n{{end}}\"\n  endif\n  let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', l:format])\n  return split(l:out, '\\n')\nendfunction\n\nfunction! go#tool#Imports() abort\n  let imports = {}\n  if go#util#IsWin()\n    let format = '{{range $f := .Imports}}{{$f}}{{printf \\\"\\n\\\"}}{{end}}'\n  else\n    let format = \"{{range $f := .Imports}}{{$f}}{{printf \\\"\\\\n\\\"}}{{end}}\"\n  endif\n  let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', l:format])\n  if l:err != 0\n    echo out\n    return imports\n  endif\n\n  for package_path in split(out, '\\n')\n    let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', '{{.Name}}', l:package_path])\n    if l:err != 0\n      echo out\n      return imports\n    endif\n    let package_name = substitute(l:out, '\\n$', '', '')\n    let imports[package_name] = package_path\n  endfor\n\n  return imports\nendfunction\n\nfunction! go#tool#Info(showstatus) abort\n  if !go#config#GoplsEnabled()\n    call go#util#EchoError(\"gopls is disabled\")\n    return\n  endif\n  call go#lsp#Info(a:showstatus)\nendfunction\n\nfunction! go#tool#PackageName() abort\n  let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', '{{.Name}}'])\n  if l:err != 0\n      return -1\n  endif\n\n  return split(out, '\\n')[0]\nendfunction\n\n\" Exists checks whether the given importpath exists or not. It returns 0 if\n\" the importpath exists under GOPATH.\nfunction! go#tool#Exists(importpath) abort\n    let [l:out, l:err] = go#util#ExecInDir(['go', 'list', a:importpath])\n    if l:err != 0\n        return -1\n    endif\n\n    return 0\nendfunction\n\nfunction! go#tool#List(package_path) abort\n  let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', '{{.ImportPath}}', a:package_path])\n  if l:err != 0\n      return -1\n  endif\n\n  return split(out, '\\n')\nendfunction\n\nfunction! go#tool#DescribeBalloon()\n  let l:fname = fnamemodify(bufname(v:beval_bufnr), ':p')\n\n  let l:winid = win_getid()\n\n  call win_gotoid(bufwinid(v:beval_bufnr))\n\n  let [l:line, l:col] = go#lsp#lsp#Position(v:beval_lnum, v:beval_col)\n  call go#lsp#Hover(l:fname, l:line, l:col, funcref('s:balloon', []))\n\n  call win_gotoid(l:winid)\n  return ''\nendfunction\n\nfunction! s:balloon(msg)\n  let l:msg = a:msg\n  if has('balloon_eval')\n    if has('balloon_multiline')\n      let l:msg = join(a:msg, \"\\n\")\n    endif\n  endif\n\n  call balloon_show(l:msg)\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/tool_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunc! Test_ExecuteInDir() abort\n  let g:go_gopls_enabled = 0\n  let l:wd = getcwd()\n  let l:tmp = gotest#write_file('a/a.go', ['package a'])\n  try\n    let l:cwd = go#util#Exec(['pwd'])\n    let l:out = go#util#ExecInDir(['pwd'])\n    call assert_notequal(l:cwd, l:out)\n    call assert_equal([l:tmp . \"/src/a\\n\", 0], l:out)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\nfunc! Test_ExecuteInDir_nodir() abort\n  let g:go_gopls_enabled = 0\n  let l:wd = getcwd()\n  let l:tmp = go#util#tempdir(\"executeindir\")\n  exe ':e ' . l:tmp . '/new-dir/a'\n\n  try\n    let l:out = go#util#ExecInDir(['pwd'])\n    call assert_equal(['', 1], l:out)\n  finally\n    call go#util#Chdir(l:wd)\n    call delete(l:tmp, 'rf')\n  endtry\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/ui.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nlet s:buf_nr = -1\n\n\"OpenWindow opens a new scratch window and put's the content into the window\nfunction! go#ui#OpenWindow(title, content, filetype) abort\n  \" Ensure there's only one return window in this session/tabpage\n  call go#util#Windo(\"unlet! w:vim_go_return_window\")\n  \" Mark the window we're leaving as such\n  let w:vim_go_return_window = 1\n\n  \" reuse existing buffer window if it exists otherwise create a new one\n  if !bufexists(s:buf_nr)\n    execute 'botright new'\n    file `=\"[\" . a:title . \"]\"`\n    let s:buf_nr = bufnr('%')\n  elseif bufwinnr(s:buf_nr) == -1\n    execute 'botright new'\n    execute s:buf_nr . 'buffer'\n  elseif bufwinnr(s:buf_nr) != bufwinnr('%')\n    execute bufwinnr(s:buf_nr) . 'wincmd w'\n  endif\n\n  \" Resize window to content length\n  exe 'resize' . len(a:content)\n\n  execute \"setlocal filetype=\".a:filetype\n\n  \" some sane default values for a readonly buffer\n  setlocal bufhidden=delete\n  setlocal buftype=nofile\n  setlocal noswapfile\n  setlocal nobuflisted\n  setlocal winfixheight\n  setlocal cursorline \" make it easy to distinguish\n  setlocal nonumber\n  setlocal norelativenumber\n  setlocal showbreak=\"\"\n\n  \" we need this to purge the buffer content\n  setlocal modifiable\n\n  \"delete everything first from the buffer\n  %delete _\n\n  \" add the content\n  call append(0, a:content)\n\n  \" delete last line that comes from the append call\n  $delete _\n\n  \" set it back to non modifiable\n  setlocal nomodifiable\n\n  \" Remove the '... [New File]' message line from the command line\n  echon\nendfunction\n\nfunction! go#ui#GetReturnWindow() abort\n  for l:wn in range(1, winnr(\"$\"))\n    if !empty(getwinvar(l:wn, \"vim_go_return_window\"))\n      return l:wn\n    endif\n  endfor\nendfunction\n\n\" CloseWindow closes the current window\nfunction! go#ui#CloseWindow() abort\n  \" Close any window associated with the ui buffer, if it's there\n  if bufexists(s:buf_nr)\n    let ui_window_number = bufwinnr(s:buf_nr)\n    if ui_window_number != -1\n      execute ui_window_number . 'close'\n    endif\n  endif\n\n  \"return to original window, if it's there\n  let l:rw = go#ui#GetReturnWindow()\n  if !empty(l:rw)\n    execute l:rw . 'wincmd w'\n    unlet! w:vim_go_return_window\n  endif\nendfunction\n\n\" OpenDefinition parses the current line and jumps to it by openening a new\n\" tab\nfunction! go#ui#OpenDefinition(filter) abort\n  let curline = getline('.')\n\n  \" don't touch our first line or any blank line\n  if curline =~ a:filter || curline =~ \"^$\"\n    \" suppress information about calling this function\n    echo \"\"\n    return\n  endif\n\n  \" format: 'interface file:lnum:coln'\n  let mx = '^\\(^\\S*\\)\\s*\\(.\\{-}\\):\\(\\d\\+\\):\\(\\d\\+\\)'\n\n  \" parse it now into the list\n  let tokens = matchlist(curline, mx)\n\n  \" convert to: 'file:lnum:coln'\n  let expr = tokens[2] . \":\" . tokens[3] . \":\" .  tokens[4]\n\n  \" jump to it in a new tab, we use explicit lgetexpr so we can later change\n  \" the behaviour via settings (like opening in vsplit instead of tab)\n  lgetexpr expr\n  tab split\n  ll 1\n\n  \" center the word\n  norm! zz\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/uri.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! go#uri#Encode(value) abort\n    return s:encode(a:value, '[^A-Za-z0-9_.~-]')\nendfunction\n\nfunction! go#uri#EncodePath(value) abort\n    let l:separator = '/'\n    if go#util#IsWin()\n      let l:separator = '\\\\'\n    endif\n    return s:encode(a:value, '[^' . l:separator . 'A-Za-z0-9_.~-]')\nendfunction\n\nfunction! s:encode(value, unreserved)\n    return substitute(\n    \\   a:value,\n    \\   a:unreserved,\n    \\   '\\=s:encodechar(submatch(0))',\n    \\   'g'\n    \\)\nendfunction\n\nfunction! go#uri#Decode(value) abort\n    return substitute(\n    \\   a:value,\n    \\   '%\\(\\x\\x\\)',\n    \\   '\\=s:decodehex(submatch(1))',\n    \\   'g'\n    \\)\nendfunction\n\nfunction! s:encodechar(value)\n  let l:idx = 0\n  let l:encoded = ''\n  while l:idx < strlen(a:value)\n    let l:byte = strpart(a:value, l:idx, 1)\n    let l:encoded = printf('%s%%%02X', l:encoded, char2nr(l:byte))\n    let l:idx += 1\n  endwhile\n\n  return l:encoded\nendfunction\n\nfunction! s:decodehex(value)\n  return eval(printf('\"\\x%s\"', a:value))\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/uri_test.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nscriptencoding utf-8\n\nfunc! Test_EncodePath_simple() abort\n\tlet l:uri = '/simple/foo'\n\tlet l:expected = '/simple/foo'\n\n\tlet l:actual = go#uri#EncodePath(l:uri)\n\tcall assert_equal(l:expected, l:actual)\nendfunc\n\nfunc! Test_EncodePath_multibyte() abort\n  let l:uri = '/multi-byte/⌘⌘'\n  let l:expected = '/multi-byte/%E2%8C%98%E2%8C%98'\n\n\tlet l:actual = go#uri#EncodePath(l:uri)\n\tcall assert_equal(l:expected, l:actual)\nendfunc\n\nfunc! Test_Decode_simple() abort\n\tlet l:uri = '/simple/foo'\n\tlet l:expected = '/simple/foo'\n\n\tlet l:actual = go#uri#Decode(l:uri)\n\tcall assert_equal(l:expected, l:actual)\nendfunc\n\nfunc! Test_Decode_multibyte() abort\n  let l:uri = '/multi-byte/%E2%8C%98%E2%8C%98'\n  let l:expected = '/multi-byte/⌘⌘'\n\tlet l:actual = go#uri#Decode(l:uri)\n\tcall assert_equal(l:expected, l:actual)\nendfunc\n\nfunc! Test_Roundtrip_simple() abort\n\tlet l:expected = '/simple/foo'\n\n\tlet l:actual = go#uri#Decode(go#uri#EncodePath(l:expected))\n\tcall assert_equal(l:expected, l:actual)\nendfunc\n\nfunc! Test_Roundtrip_multibyte() abort\n  let l:expected = '/multi-byte/⌘⌘'\n\n\tlet l:actual = go#uri#Decode(go#uri#EncodePath(l:expected))\n  call assert_equal(l:expected, l:actual)\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/go/util.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\n\" PathSep returns the appropriate OS specific path separator.\nfunction! go#util#PathSep() abort\n  if go#util#IsWin()\n    return '\\'\n  endif\n  return '/'\nendfunction\n\n\" PathListSep returns the appropriate OS specific path list separator.\nfunction! go#util#PathListSep() abort\n  if go#util#IsWin()\n    return \";\"\n  endif\n  return \":\"\nendfunction\n\n\" LineEnding returns the correct line ending, based on the current fileformat\nfunction! go#util#LineEnding() abort\n  if &fileformat == 'dos'\n    return \"\\r\\n\"\n  elseif &fileformat == 'mac'\n    return \"\\r\"\n  endif\n\n  return \"\\n\"\nendfunction\n\n\" Join joins any number of path elements into a single path, adding a\n\" Separator if necessary and returns the result\nfunction! go#util#Join(...) abort\n  return join(a:000, go#util#PathSep())\nendfunction\n\n\" IsWin returns 1 if current OS is Windows or 0 otherwise\n\" Note that has('win32') is always 1 when has('win64') is 1, so has('win32') is enough.\nfunction! go#util#IsWin() abort\n  return has('win32')\nendfunction\n\n\" IsMac returns 1 if current OS is macOS or 0 otherwise.\nfunction! go#util#IsMac() abort\n  return has('mac') ||\n        \\ has('macunix') ||\n        \\ has('gui_macvim') ||\n        \\ go#util#Exec(['uname'])[0] =~? '^darwin'\nendfunction\n\n \" Checks if using:\n \" 1) Windows system,\n \" 2) And has cygpath executable,\n \" 3) And uses *sh* as 'shell'\nfunction! go#util#IsUsingCygwinShell()\n  return go#util#IsWin() && executable('cygpath') && &shell =~ '.*sh.*'\nendfunction\n\n\" Check if Vim jobs API is supported.\n\"\n\" The (optional) first parameter can be added to indicate the 'cwd' or 'env'\n\" parameters will be used, which wasn't added until a later version.\nfunction! go#util#has_job(...) abort\n  return has('job') || has('nvim')\nendfunction\n\nlet s:env_cache = {}\n\n\" env returns the go environment variable for the given key. Where key can be\n\" GOARCH, GOOS, GOROOT, etc... It caches the result and returns the cached\n\" version.\nfunction! go#util#env(key) abort\n  let l:key = tolower(a:key)\n  if has_key(s:env_cache, l:key)\n    return s:env_cache[l:key]\n  endif\n\n  if executable('go')\n    let l:var = call('go#util#'.l:key, [])\n    if go#util#ShellError() != 0\n      call go#util#EchoError(printf(\"'go env %s' failed\", toupper(l:key)))\n      return ''\n    endif\n  else\n    let l:var = eval(\"$\".toupper(a:key))\n  endif\n\n  let s:env_cache[l:key] = l:var\n  return l:var\nendfunction\n\n\" gobin returns 'go env GOBIN'. This is an internal function and shouldn't be\n\" used. Use go#util#env('gobin') instead.\nfunction! go#util#gobin() abort\n  return substitute(s:exec(['go', 'env', 'GOBIN'])[0], '\\n', '', 'g')\nendfunction\n\n\" goarch returns 'go env GOARCH'. This is an internal function and shouldn't\n\" be used. Use go#util#env('goarch') instead.\nfunction! go#util#goarch() abort\n  return substitute(s:exec(['go', 'env', 'GOARCH'])[0], '\\n', '', 'g')\nendfunction\n\n\" goos returns 'go env GOOS'. This is an internal function and shouldn't be\n\" used. Use go#util#env('goos') instead.\nfunction! go#util#goos() abort\n  return substitute(s:exec(['go', 'env', 'GOOS'])[0], '\\n', '', 'g')\nendfunction\n\n\" goroot returns 'go env GOROOT'. This is an internal function and shouldn't\n\" be used. Use go#util#env('goroot') instead.\nfunction! go#util#goroot() abort\n  return substitute(s:exec(['go', 'env', 'GOROOT'])[0], '\\n', '', 'g')\nendfunction\n\n\" gopath returns 'go env GOPATH'. This is an internal function and shouldn't\n\" be used. Use go#util#env('gopath') instead.\nfunction! go#util#gopath() abort\n  return substitute(s:exec(['go', 'env', 'GOPATH'])[0], '\\n', '', 'g')\nendfunction\n\n\" gomod returns 'go env GOMOD'. gomod changes depending on the folder. Don't\n\" use go#util#env as it caches the value.\nfunction! go#util#gomod() abort\n  return substitute(s:exec(['go', 'env', 'GOMOD'])[0], '\\n', '', 'g')\nendfunction\n\n\" gomodcache returns 'go env GOMODCACHE'. This is an internal function and\n\" shouldn't be used. Use go#util#env('gomodcache') instead.\nfunction! go#util#gomodcache() abort\n  return substitute(s:exec(['go', 'env', 'GOMODCACHE'])[0], '\\n', '', 'g')\nendfunction\n\n\" hostosarch returns the OS and ARCH values that the go binary is intended for.\nfunction! go#util#hostosarch() abort\n  let [l:hostos, l:err] = s:exec(['go', 'env', 'GOHOSTOS'])\n  let [l:hostarch, l:err] = s:exec(['go', 'env', 'GOHOSTARCH'])\n  return [substitute(l:hostos, '\\n', '', 'g'), substitute(l:hostarch, '\\n', '', 'g')]\nendfunction\n\n\" go#util#ModuleRoot returns the root directory of the module of the current\n\" buffer. An optional argument can be provided to check an arbitrary\n\" directory.\nfunction! go#util#ModuleRoot(...) abort\n  let l:wd = ''\n  if a:0 > 0\n    let l:wd = go#util#Chdir(a:1)\n  endif\n  try\n    let [l:out, l:err] = go#util#ExecInDir(['go', 'env', 'GOMOD'])\n    if l:err != 0\n      return -1\n    endif\n  finally\n    if l:wd != ''\n      call go#util#Chdir(l:wd)\n    endif\n  endtry\n\n  let l:module = split(l:out, '\\n', 1)[0]\n\n  \" When run with `GO111MODULE=on and not in a module directory, the module will be reported as /dev/null.\n  let l:fakeModule = '/dev/null'\n  if go#util#IsWin()\n    let l:fakeModule = 'NUL'\n  endif\n\n  if l:fakeModule == l:module\n    return expand('%:p:h')\n  endif\n\n  return resolve(fnamemodify(l:module, ':p:h'))\nendfunction\n\n\" Run a shell command.\n\"\n\" It will temporary set the shell to /bin/sh for Unix-like systems if possible,\n\" so that we always use a standard POSIX-compatible Bourne shell (and not e.g.\n\" csh, fish, etc.) See #988 and #1276.\nfunction! s:system(cmd, ...) abort\n  \" Preserve original shell, shellredir and shellcmdflag values\n  let l:shell = &shell\n  let l:shellredir = &shellredir\n  let l:shellcmdflag = &shellcmdflag\n  let l:shellquote = &shellquote\n  let l:shellxquote = &shellxquote\n\n  if !go#util#IsWin() && executable('/bin/sh')\n      set shell=/bin/sh shellredir=>%s\\ 2>&1 shellcmdflag=-c\n  endif\n\n  if go#util#IsWin()\n    if executable($COMSPEC)\n      let &shell = $COMSPEC\n      set shellcmdflag=/C\n      set shellquote&\n      set shellxquote&\n    endif\n  endif\n\n  try\n    return call('system', [a:cmd] + a:000)\n  finally\n    \" Restore original values\n    let &shell = l:shell\n    let &shellredir = l:shellredir\n    let &shellcmdflag = l:shellcmdflag\n    let &shellquote = l:shellquote\n    let &shellxquote = l:shellxquote\n  endtry\nendfunction\n\n\" System runs a shell command \"str\". Every arguments after \"str\" is passed to\n\" stdin.\nfunction! go#util#System(str, ...) abort\n  return call('s:system', [a:str] + a:000)\nendfunction\n\n\" Exec runs a shell command \"cmd\", which must be a list, one argument per item.\n\" Every list entry will be automatically shell-escaped\n\" Every other argument is passed to stdin.\nfunction! go#util#Exec(cmd, ...) abort\n  if len(a:cmd) == 0\n    call go#util#EchoError(\"go#util#Exec() called with empty a:cmd\")\n    return ['', 1]\n  endif\n\n  let l:bin = a:cmd[0]\n\n  \" Lookup the full path, respecting settings such as 'go_bin_path'. On errors,\n  \" CheckBinPath will show a warning for us.\n  let l:bin = go#path#CheckBinPath(l:bin)\n  if empty(l:bin)\n    return ['', 1]\n  endif\n\n  \" Finally execute the command using the full, resolved path. Do not pass the\n  \" unmodified command as the correct program might not exist in $PATH.\n  return call('s:exec', [[l:bin] + a:cmd[1:]] + a:000)\nendfunction\n\n\" ExecInDir will execute cmd with the working directory set to the current\n\" buffer's directory.\nfunction! go#util#ExecInDir(cmd, ...) abort\n  let l:wd = expand('%:p:h')\n  return call('go#util#ExecInWorkDir', [a:cmd, l:wd] + a:000)\nendfunction\n\n\" ExecInWorkDir will execute cmd with the working diretory set to wd. Additional arguments will be passed\n\" to cmd.\nfunction! go#util#ExecInWorkDir(cmd, wd, ...) abort\n  if !isdirectory(a:wd)\n    return ['', 1]\n  endif\n\n  let l:dir = go#util#Chdir(a:wd)\n  try\n    let [l:out, l:err] = call('go#util#Exec', [a:cmd] + a:000)\n  finally\n    call go#util#Chdir(l:dir)\n  endtry\n  return [l:out, l:err]\nendfunction\n\nfunction! s:exec(cmd, ...) abort\n  let l:bin = a:cmd[0]\n  let l:cmd = go#util#Shelljoin([l:bin] + a:cmd[1:])\n  if go#util#HasDebug('shell-commands')\n    call go#util#EchoInfo('shell command: ' . l:cmd)\n  endif\n\n  let l:out = call('s:system', [l:cmd] + a:000)\n  return [l:out, go#util#ShellError()]\nendfunction\n\nfunction! go#util#ShellError() abort\n  return v:shell_error\nendfunction\n\n\" StripPath strips the path's last character if it's a path separator.\n\" example: '/foo/bar/'  -> '/foo/bar'\nfunction! go#util#StripPathSep(path) abort\n  let last_char = strlen(a:path) - 1\n  if a:path[last_char] == go#util#PathSep()\n    return strpart(a:path, 0, last_char)\n  endif\n\n  return a:path\nendfunction\n\n\" StripTrailingSlash strips the trailing slash from the given path list.\n\" example: ['/foo/bar/']  -> ['/foo/bar']\nfunction! go#util#StripTrailingSlash(paths) abort\n  return map(copy(a:paths), 'go#util#StripPathSep(v:val)')\nendfunction\n\n\" Shelljoin returns a shell-safe string representation of arglist. The\n\" {special} argument of shellescape() may optionally be passed.\nfunction! go#util#Shelljoin(arglist, ...) abort\n  \" Preserve original shell. This needs to be kept in sync with how s:system\n  \" sets shell.\n  let l:shell = &shell\n\n  try\n    if !go#util#IsWin() && executable('/bin/sh')\n        set shell=/bin/sh\n    endif\n\n    if go#util#IsWin()\n      if executable($COMSPEC)\n        let &shell = $COMSPEC\n      endif\n    endif\n\n    let ssl_save = &shellslash\n    if has(\"win32\")\n      set noshellslash\n    endif\n    if a:0\n      return join(map(copy(a:arglist), 'shellescape(v:val, ' . a:1 . ')'), ' ')\n    endif\n\n    return join(map(copy(a:arglist), 'shellescape(v:val)'), ' ')\n  finally\n    \" Restore original values\n    let &shellslash = ssl_save\n    let &shell = l:shell\n  endtry\nendfunction\n\n\" Shelllist returns a shell-safe representation of the items in the given\n\" arglist. The {special} argument of shellescape() may optionally be passed.\nfunction! go#util#Shelllist(arglist, ...) abort\n  try\n    let ssl_save = &shellslash\n    if has(\"win32\")\n      set noshellslash\n    endif\n    if a:0\n      return map(copy(a:arglist), 'go#util#Shelljoin(v:val, ' . a:1 . ')')\n    endif\n    return map(copy(a:arglist), 'go#util#Shelljoin(v:val)')\n  finally\n    let &shellslash = ssl_save\n  endtry\nendfunction\n\n\" Returns the byte offset for line and column\nfunction! go#util#Offset(line, col) abort\n  if &encoding != 'utf-8'\n    let sep = go#util#LineEnding()\n    let buf = a:line == 1 ? '' : (join(getline(1, a:line-1), sep) . sep)\n    let buf .= a:col == 1 ? '' : getline('.')[:a:col-2]\n    return len(iconv(buf, &encoding, 'utf-8'))\n  endif\n  return line2byte(a:line) + (a:col-2)\nendfunction\n\"\n\" Returns the byte offset for the cursor\nfunction! go#util#OffsetCursor() abort\n  return go#util#Offset(line('.'), col('.'))\nendfunction\n\n\" Windo is like the built-in :windo, only it returns to the window the command\n\" was issued from\nfunction! go#util#Windo(command) abort\n  let s:currentWindow = winnr()\n  try\n    execute \"windo \" . a:command\n  finally\n    execute s:currentWindow. \"wincmd w\"\n    unlet s:currentWindow\n  endtry\nendfunction\n\n\" snippetcase converts the given word to given preferred snippet setting type\n\" case.\nfunction! go#util#snippetcase(word) abort\n  let l:snippet_case = go#config#AddtagsTransform()\n  if l:snippet_case == \"snakecase\"\n    return go#util#snakecase(a:word)\n  elseif l:snippet_case == \"camelcase\"\n    return go#util#camelcase(a:word)\n  else\n    return a:word \" do nothing\n  endif\nendfunction\n\n\" snakecase converts a string to snake case. i.e: FooBar -> foo_bar\n\" Copied from tpope/vim-abolish\nfunction! go#util#snakecase(word) abort\n  let word = substitute(a:word, '::', '/', 'g')\n  let word = substitute(word, '\\(\\u\\+\\)\\(\\u\\l\\)', '\\1_\\2', 'g')\n  let word = substitute(word, '\\(\\l\\|\\d\\)\\(\\u\\)', '\\1_\\2', 'g')\n  let word = substitute(word, '[.-]', '_', 'g')\n  let word = tolower(word)\n  return word\nendfunction\n\n\" camelcase converts a string to camel case. e.g. FooBar or foo_bar will become\n\" fooBar.\n\" Copied from tpope/vim-abolish.\nfunction! go#util#camelcase(word) abort\n  let word = substitute(a:word, '-', '_', 'g')\n  if word !~# '_' && word =~# '\\l'\n    return substitute(word, '^.', '\\l&', '')\n  else\n    return substitute(word, '\\C\\(_\\)\\=\\(.\\)', '\\=submatch(1)==\"\"?tolower(submatch(2)) : toupper(submatch(2))','g')\n  endif\nendfunction\n\n\" pascalcase converts a string to 'PascalCase'. e.g. fooBar or foo_bar will\n\" become FooBar.\nfunction! go#util#pascalcase(word) abort\n  let word = go#util#camelcase(a:word)\n  return toupper(word[0]) . word[1:]\nendfunction\n\n\" Echo a message to the screen and highlight it with the group in a:hi.\n\"\n\" The message can be a list or string; every line with be :echomsg'd separately.\nfunction! s:echo(msg, hi)\n  let l:msg = []\n  if type(a:msg) != type([])\n    let l:msg = split(a:msg, \"\\n\")\n  else\n    let l:msg = a:msg\n  endif\n\n  \" Tabs display as ^I or <09>, so manually expand them.\n  let l:msg = map(l:msg, 'substitute(v:val, \"\\t\", \"        \", \"\")')\n\n  exe 'echohl ' . a:hi\n  for line in l:msg\n    echom \"vim-go: \" . line\n  endfor\n  echohl None\nendfunction\n\nfunction! go#util#EchoSuccess(msg)\n  call s:echo(a:msg, 'Function')\nendfunction\nfunction! go#util#EchoError(msg)\n  call s:echo(a:msg, 'ErrorMsg')\nendfunction\nfunction! go#util#EchoWarning(msg)\n  call s:echo(a:msg, 'WarningMsg')\nendfunction\nfunction! go#util#EchoProgress(msg)\n  redraw\n  call s:echo(a:msg, 'Identifier')\nendfunction\nfunction! go#util#EchoInfo(msg)\n  call s:echo(a:msg, 'Debug')\nendfunction\n\n\" Get all lines in the buffer as a a list.\nfunction! go#util#GetLines()\n  let buf = getline(1, '$')\n  if &encoding != 'utf-8'\n    let buf = map(buf, 'iconv(v:val, &encoding, \"utf-8\")')\n  endif\n  if &l:fileformat == 'dos'\n    \" XXX: line2byte() depend on 'fileformat' option.\n    \" so if fileformat is 'dos', 'buf' must include '\\r'.\n    let buf = map(buf, 'v:val.\"\\r\"')\n  endif\n  return buf\nendfunction\n\n\" Convert the current buffer to the \"archive\" format of\n\" golang.org/x/tools/go/buildutil:\n\" https://godoc.org/golang.org/x/tools/go/buildutil#ParseOverlayArchive\n\"\n\" > The archive consists of a series of files. Each file consists of a name, a\n\" > decimal file size and the file contents, separated by newlinews. No newline\n\" > follows after the file contents.\nfunction! go#util#archive()\n    let l:buffer = join(go#util#GetLines(), \"\\n\")\n    return expand(\"%:p:gs!\\\\!/!\") . \"\\n\" . strlen(l:buffer) . \"\\n\" . l:buffer\nendfunction\n\n\" Make a named temporary directory which starts with \"prefix\".\n\"\n\" Unfortunately Vim's tempname() is not portable enough across various systems;\n\" see: https://github.com/mattn/vim-go/pull/3#discussion_r138084911\nfunction! go#util#tempdir(prefix) abort\n  \" See :help tempfile\n  if go#util#IsWin()\n    let l:dirs = [$TMP, $TEMP, 'c:\\tmp', 'c:\\temp']\n  else\n    let l:dirs = [$TMPDIR, '/tmp', './', $HOME]\n  endif\n\n  let l:dir = ''\n  for l:d in dirs\n    if !empty(l:d) && filewritable(l:d) == 2\n      let l:dir = l:d\n      break\n    endif\n  endfor\n\n  if l:dir == ''\n    call go#util#EchoError('Unable to find directory to store temporary directory in')\n    return\n  endif\n\n  \" Not great randomness, but \"good enough\" for our purpose here.\n  let l:rnd = sha256(printf('%s%s', reltimestr(reltime()), fnamemodify(bufname(''), \":p\")))\n  let l:tmp = printf(\"%s/%s%s\", l:dir, a:prefix, l:rnd)\n  call mkdir(l:tmp, 'p', 0700)\n  return l:tmp\nendfunction\n\n\" Report if the user enabled a debug flag in g:go_debug.\nfunction! go#util#HasDebug(flag)\n  return index(go#config#Debug(), a:flag) >= 0\nendfunction\n\nfunction! go#util#OpenBrowser(url) abort\n    let l:cmd = go#config#PlayBrowserCommand()\n    if len(l:cmd) == 0\n        redraw\n        echohl WarningMsg\n        echo \"It seems that you don't have general web browser. Open URL below.\"\n        echohl None\n        echo a:url\n        return\n    endif\n\n    \" if setting starts with a !.\n    if l:cmd =~ '^!'\n        let l:cmd = substitute(l:cmd, '%URL%', '\\=escape(shellescape(a:url), \"#\")', 'g')\n        silent! exec l:cmd\n    elseif cmd =~ '^:[A-Z]'\n        let l:cmd = substitute(l:cmd, '%URL%', '\\=escape(a:url,\"#\")', 'g')\n        exec l:cmd\n    else\n        let l:cmd = substitute(l:cmd, '%URL%', '\\=shellescape(a:url)', 'g')\n        call go#util#System(l:cmd)\n    endif\nendfunction\n\nfunction! go#util#ParseErrors(lines) abort\n  let errors = []\n\n  for line in a:lines\n    let fatalerrors = matchlist(line, '^\\(fatal error:.*\\)$')\n    let tokens = matchlist(line, '^\\s*\\(.\\{-}\\):\\(\\d\\+\\):\\s*\\(.*\\)')\n\n    if !empty(fatalerrors)\n      call add(errors, {\"text\": fatalerrors[1]})\n    elseif !empty(tokens)\n      \" strip endlines of form ^M\n      let out = substitute(tokens[3], '\\r$', '', '')\n\n      call add(errors, {\n            \\ \"filename\" : fnamemodify(tokens[1], ':p'),\n            \\ \"lnum\"     : tokens[2],\n            \\ \"text\"     : out,\n            \\ })\n    elseif !empty(errors)\n      \" Preserve indented lines.\n      \" This comes up especially with multi-line test output.\n      if match(line, '^\\s') >= 0\n        call add(errors, {\"text\": substitute(line, '\\r$', '', '')})\n      endif\n    endif\n  endfor\n\n  return errors\nendfunction\n\nfunction! go#util#ShowInfo(info)\n  if empty(a:info)\n    return\n  endif\n\n  echo \"vim-go: \" | echohl Function | echon a:info | echohl None\nendfunction\n\n\" go#util#SetEnv takes the name of an environment variable and what its value\n\" should be and returns a function that will restore it to its original value.\nfunction! go#util#SetEnv(name, value) abort\n  let l:state = {}\n\n  if len(a:name) == 0\n    return function('s:noop', [], l:state)\n  endif\n\n  let l:remove = 0\n  if exists('$' . a:name)\n    let l:oldvalue = eval('$' . a:name)\n  else\n    let l:remove = 1\n  endif\n\n  \" wrap the value in single quotes so that it will work on windows when there\n  \" are backslashes present in the value (e.g. $PATH).\n  call execute('let $' . a:name . \" = '\" . a:value . \"'\")\n\n  if l:remove\n    return function('s:unset', [a:name], l:state)\n  endif\n\n  return function('go#util#SetEnv', [a:name, l:oldvalue], l:state)\nendfunction\n\nfunction! go#util#ClearHighlights(group) abort\n  if has('textprop')\n    \" the property type may not exist when syntax highlighting is not enabled.\n    if empty(prop_type_get(a:group))\n      return\n    endif\n    if !has('patch-8.1.1035')\n      return prop_remove({'type': a:group, 'all': 1}, 1, line('$'))\n    endif\n    return prop_remove({'type': a:group, 'all': 1})\n  endif\n\n  if exists(\"*matchaddpos\")\n    return s:clear_group_from_matches(a:group)\n  endif\nendfunction\n\nfunction! s:clear_group_from_matches(group) abort\n  let l:cleared = 0\n\n  let m = getmatches()\n  for item in m\n    if item['group'] == a:group\n      call matchdelete(item['id'])\n      let l:cleared = 1\n    endif\n  endfor\n\n  return l:cleared\nendfunction\n\nfunction! s:unset(name) abort\n  try\n    \" unlet $VAR was introducted in Vim 8.0.1832, which is newer than the\n    \" minimal version that vim-go supports. Set the environment variable to\n    \" the empty string in that case. It's not perfect, but it will work fine\n    \" for most things, and is really the best alternative that's available.\n    if !has('patch-8.0.1832')\n      call go#util#SetEnv(a:name, '')\n      return\n    endif\n\n    call execute('unlet $' . a:name)\n  catch\n    call go#util#EchoError(printf('could not unset $%s: %s', a:name, v:exception))\n  endtry\nendfunction\n\nfunction! s:noop(...) abort dict\nendfunction\n\n\" go#util#HighlightPositions highlights using text properties if possible and\n\" falls back to matchaddpos() if necessary. It works around matchaddpos()'s\n\" limit of only 8 positions per call by calling matchaddpos() with no more\n\" than 8 positions per call.\n\"\n\" pos should be a list of 3 element lists. The lists should be [line, col,\n\" length] as used by matchaddpos().\nfunction! go#util#HighlightPositions(group, pos) abort\n  if has('textprop')\n    for l:pos in a:pos\n      \" use a single line prop by default\n      let l:prop = {'type': a:group, 'length': l:pos[2]}\n\n      let l:line = getline(l:pos[0])\n\n      \" l:max is the 1-based index within the buffer of the first character after l:pos.\n      let l:max = line2byte(l:pos[0]) + l:pos[1] + l:pos[2] - 1\n      if has('patch-8.2.115')\n        \" Use byte2line as long as 8.2.115 (which resolved\n        \" https://github.com/vim/vim/issues/5334) is available.\n        let l:end_lnum = byte2line(l:max)\n\n        \" specify end line and column if needed.\n        if l:pos[0] != l:end_lnum\n          let l:end_col = l:max - line2byte(l:end_lnum)\n          let l:prop = {'type': a:group, 'end_lnum': l:end_lnum, 'end_col': l:end_col}\n        endif\n      elseif l:pos[1] + l:pos[2] - 1 > len(l:line)\n        let l:end_lnum = l:pos[0]\n        while line2byte(l:end_lnum+1) < l:max\n          let l:end_lnum += 1\n        endwhile\n\n        \" l:end_col is the full length - the byte position of l:end_lnum +\n        \" the number of newlines (number of newlines is l:end_lnum -\n        \" l:pos[0].\n        let l:end_col = l:max - line2byte(l:end_lnum) + l:end_lnum - l:pos[0]\n        let l:prop = {'type': a:group, 'end_lnum': l:end_lnum, 'end_col': l:end_col}\n      endif\n      try\n        call prop_add(l:pos[0], l:pos[1], l:prop)\n      catch\n        \" Swallow any exceptions encountered while trying to add the property\n        \" Due to the asynchronous nature, it's possible that the buffer has\n        \" changed since the buffer was analyzed and that the specified\n        \" position is no longer valid.\n      endtry\n    endfor\n    return\n  endif\n\n  if exists('*matchaddpos')\n    return s:matchaddpos(a:group, a:pos)\n  endif\nendfunction\n\n\" s:matchaddpos works around matchaddpos()'s limit of only 8 positions per\n\" call by calling matchaddpos() with no more than 8 positions per call.\nfunction! s:matchaddpos(group, pos) abort\n  let l:partitions = []\n  let l:partitionsIdx = 0\n  let l:posIdx = 0\n  for l:pos in a:pos\n    if l:posIdx % 8 == 0\n      let l:partitions = add(l:partitions, [])\n      let l:partitionsIdx = len(l:partitions) - 1\n    endif\n    let l:partitions[l:partitionsIdx] = add(l:partitions[l:partitionsIdx], l:pos)\n    let l:posIdx = l:posIdx + 1\n  endfor\n\n  for l:positions in l:partitions\n    call matchaddpos(a:group, l:positions)\n  endfor\nendfunction\n\nfunction! go#util#Chdir(dir) abort\n  if !exists('*chdir')\n    let l:olddir = getcwd()\n    let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'\n    execute printf('%s %s', cd, fnameescape(a:dir))\n    return l:olddir\n  endif\n  return chdir(a:dir)\nendfunction\n\nfunction! go#util#testLine() abort\n  \" search flags legend (used only)\n  \" 'b' search backward instead of forward\n  \" 'c' accept a match at the cursor position\n  \" 'n' do Not move the cursor\n  \" 'W' don't wrap around the end of the file\n  \"\n  \" for the full list\n  \" :help search\n  let l:line = search('^func \\(Test\\|Example\\)', \"bcnW\")\n  return l:line\nendfunction\n\n\" go#util#TestName returns the name of the test function that preceeds the\n\" cursor.\nfunction! go#util#TestName() abort\n  let l:line = go#util#testLine()\n\n  if l:line == 0\n    return ''\n  endif\n\n  let l:decl = getline(l:line)\n  return split(split(l:decl, \" \")[1], \"(\")[0]\nendfunction\n\n\" go#util#TestNamesInFile returns the names of the test function in the\n\" current file.\nfunction! go#util#TestNamesInFile() abort\n  let l:startpos = getpos('.')\n\n  let l:lines = []\n  call cursor('$', 1)\n  let l:line = go#util#testLine()\n  while l:line isnot 0\n    let l:lines = add(l:lines, l:line)\n    call cursor(l:line-1, 1)\n    let l:line = go#util#testLine()\n  endwhile\n\n  call setpos('.', l:startpos)\n\n  let l:tests = []\n\n  \" iterate over the lines in their reverse order, because they'll be in\n  \" reverse order, but returning the test names in file order makes the most\n  \" sense.\n  for l:line in reverse(l:lines)\n    let l:decl = getline(l:line)\n    let l:tests = add(l:tests, split(split(l:decl, \" \")[1], \"(\")[0])\n  endfor\n\n  return l:tests\nendfunction\n\nfunction! go#util#ExpandPattern(...) abort\n  let l:packages = []\n  for l:pattern in a:000\n    let l:pkgs = go#tool#List(l:pattern)\n    if l:pkgs is -1\n      call go#util#EchoError('could not expand package pattern')\n      continue\n    endif\n\n    let l:packages = extend(l:packages, l:pkgs)\n    call go#util#EchoInfo(printf(\"l:packages = %s, l:pkgs = %s\", l:packages, l:pkgs))\n  endfor\n\n  return uniq(sort(l:packages))\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/gotest.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\n\" Write a Go file to a temporary directory and append this directory to\n\" $GOPATH.\n\"\n\" The file will written to a:path, which is relative to the temporary\n\" directory, and this file will be loaded as the current buffer.\n\"\n\" A Go module will be configured in the first segment of a:path within the\n\" temporary directory. The module's name will be prefixed with vim-go.test/\n\" followed by the first segment in a:path.\n\"\n\" The current directory will be changed to the parent directory of module\n\" root.\n\"\n\" The cursor will be placed on the character before any 0x1f byte.\n\"\n\" The full path to the created directory is returned, it is the caller's\n\" responsibility to clean that up!\nfun! gotest#write_file(path, contents) abort\n  let l:dir = go#util#tempdir(\"vim-go-test/testrun/\")\n  let $GOPATH .= ':' . l:dir\n  let l:full_path = l:dir . '/src/' . a:path\n\n  call mkdir(fnamemodify(l:full_path, ':h'), 'p')\n  call writefile(a:contents, l:full_path)\n  call s:setupproject(printf('%s/src', l:dir), a:path)\n\n  silent exe 'e! ' . a:path\n\n  \" Set cursor.\n  let l:lnum = 1\n  for l:line in a:contents\n    let l:m = stridx(l:line, \"\\x1f\")\n    if l:m > -1\n      call cursor(l:lnum, l:m)\n      call setline('.', substitute(getline('.'), \"\\x1f\", '', ''))\n      silent noautocmd w!\n\n      if go#config#GoplsEnabled()\n        call go#lsp#DidClose(expand('%:p'))\n        call go#lsp#DidOpen(expand('%:p'))\n      endif\n\n      break\n    endif\n\n    let l:lnum += 1\n  endfor\n\n  return l:dir\nendfun\n\n\" Load a fixture file from test-fixtures.\n\"\n\" The file will be copied to a new GOPATH-compliant temporary directory and\n\" loaded as the current buffer.\n\"\n\" A Go module will be configured in the first segment of a:path within the\n\" temporary directory. The module's name will be prefixed with vim-go.test/\n\" followed by the first segment in a:path.\n\"\n\" The current directory will be changed to the parent directory of module\n\" root.\nfun! gotest#load_fixture(path) abort\n  if go#util#has_job()\n    call go#lsp#CleanWorkspaces()\n  endif\n  let l:dir = go#util#tempdir(\"vim-go-test/testrun/\")\n  let $GOPATH .= ':' . l:dir\n  let l:full_path = l:dir . '/src/' . a:path\n\n  call mkdir(fnamemodify(l:full_path, ':h'), 'p')\n  call s:setupproject(printf('%s/src', l:dir), a:path)\n  silent exe 'noautocmd e! ' . a:path\n  silent exe printf('read %s/test-fixtures/%s', g:vim_go_root, a:path)\n  silent noautocmd w!\n  if go#util#has_job()\n    call go#lsp#AddWorkspaceDirectory(fnamemodify(l:full_path, ':p:h'))\n  endif\n\n  return l:dir\nendfun\n\n\" Diff the contents of the current buffer to a:want, which should be a list.\n\" If a:skipHeader is true we won't bother with the package and import\n\" declarations; so e.g.:\n\"\n\"     let l:diff = s:assert_buffer(1, ['_ = mail.Address{}'])\n\"\n\" will pass, whereas otherwise you'd have to:\n\"\n\"     let l:diff = s:assert_buffer(0, ['package main', 'import \"net/mail\", '_ = mail.Address{}'])\nfun! gotest#assert_buffer(skipHeader, want) abort\n  let l:buffer = go#util#GetLines()\n\n  if a:skipHeader\n    for l:lnum in range(0, len(l:buffer) - 1)\n      \" Bit rudimentary, but works reasonably well.\n      if match(l:buffer[l:lnum], '^\\v(func|var|const|import \\(|\\))') > -1\n        \" vint bug: https://github.com/Kuniwak/vint/issues/179\n        \" vint: -ProhibitUsingUndeclaredVariable\n        let l:buffer = l:buffer[l:lnum:len(l:buffer)]\n        break\n      endif\n    endfor\n  endif\n\n  \" Using ' is often easier so we don't have to escape \".\n  let l:want = map(a:want, 'substitute(v:val, \"\\\\\\\\t\", \"\\t\", \"\")')\n\n  let l:tmp = go#util#tempdir('assert_buffer')\n  try\n    call writefile(l:buffer, l:tmp . '/have')\n    call writefile(l:want, l:tmp . '/want')\n    call go#fmt#run('gofmt', l:tmp . '/have', l:tmp . '/have')\n    call go#fmt#run('gofmt', l:tmp . '/want', l:tmp . '/want')\n    let [l:out, l:err] = go#util#Exec([\"diff\", \"-u\", l:tmp . '/want', l:tmp . '/have'])\n  finally\n    call delete(l:tmp . '/have')\n    call delete(l:tmp . '/want')\n    call delete(l:tmp, 'd')\n  endtry\n\n  if l:err || l:out != ''\n    let v:errors = extend(v:errors, split(l:out, \"\\n\"))\n  endif\nendfun\n\n\" Diff the contents of the current buffer to the fixture file in a:path.\nfun! gotest#assert_fixture(path) abort\n  let l:want = readfile(printf('%s/test-fixtures/%s', g:vim_go_root, a:path))\n  call gotest#assert_buffer(0, l:want)\nendfun\n\nfunc! gotest#assert_quickfix(got, want) abort\n  call assert_equal(len(a:want), len(a:got), \"number of errors\")\n  if len(a:want) != len(a:got)\n    return assert_equal(a:want, a:got)\n  endif\n\n  let l:retval = 0\n  let i = 0\n\n  while i < len(a:want)\n    let want_item = a:want[i]\n    let got_item = a:got[i]\n    let i += 1\n\n    let l:retval = assert_equal(want_item.bufnr, got_item.bufnr, \"bufnr\") || l:retval\n    let l:retval = assert_equal(want_item.lnum, got_item.lnum, \"lnum\") || l:retval\n    let l:retval = assert_equal(want_item.col, got_item.col, \"col\") || l:retval\n    let l:retval = assert_equal(want_item.vcol, got_item.vcol, \"vcol\") || l:retval\n    let l:retval = assert_equal(want_item.nr, got_item.nr, \"nr\") || l:retval\n    let l:retval = assert_equal(want_item.pattern, got_item.pattern, \"pattern\") || l:retval\n    let l:retval = assert_equal(want_item.text, got_item.text, \"text\") || l:retval\n    let l:retval = assert_equal(want_item.type, got_item.type, \"type\") || l:retval\n    let l:retval = assert_equal(want_item.valid, got_item.valid, \"valid\") || l:retval\n  endwhile\n\n  return l:retval\nendfunc\n\n\" s:setupproject sets up a Go module in dir rooted at the first segment of\n\" path and changes the current directory to the parent directory of the\n\" project root.\nfunc! s:setupproject(dir, path) abort\n  let l:projectdir = s:projectdir(a:path)\n  let l:mod = printf('vim-go.test/%s', l:projectdir)\n  let l:modroot = printf('%s/%s', a:dir, l:projectdir)\n  call s:creategomod(l:mod, l:modroot)\n  call go#util#Chdir(a:dir)\nendfunc\n\nfunc! s:creategomod(modname, dir) abort\n  call go#util#ExecInWorkDir(['go', 'mod', 'init', a:modname], a:dir)\nendfunc\n\n\" s:project dir returns the first element of path.\nfunc! s:projectdir(path) abort\n  let l:path = a:path\n  let l:next = fnamemodify(l:path, ':h')\n  while l:next isnot '.'\n    let l:path = l:next\n    let l:next = fnamemodify(l:path, ':h')\n  endwhile\n\n  return l:path\nendfunc\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "autoload/unite/sources/decls.vim",
    "content": "let s:save_cpo = &cpoptions\nset cpoptions&vim\n\nlet s:source = {\n      \\ 'name': 'decls',\n      \\ 'description': 'GoDecls implementation for unite',\n      \\ 'syntax': 'uniteSource__Decls',\n      \\ 'action_table': {},\n      \\ 'hooks': {},\n      \\ }\n\nfunction! unite#sources#decls#define()\n  return s:source\nendfunction\n\nfunction! s:source.gather_candidates(args, context) abort\n  let l:bin_path = go#path#CheckBinPath('motion')\n  if empty(l:bin_path)\n    return []\n  endif\n\n  let l:path = expand(get(a:args, 0, '%:p:h'))\n  if isdirectory(l:path)\n    let l:mode = 'dir'\n  elseif filereadable(l:path)\n    let l:mode = 'file'\n  else\n    return []\n  endif\n\n  let l:include = go#config#DeclsIncludes()\n  let l:command = printf('%s -format vim -mode decls -include %s -%s %s', l:bin_path, l:include, l:mode, shellescape(l:path))\n  let l:candidates = []\n  try\n    let l:result = eval(unite#util#system(l:command))\n    let l:candidates = get(l:result, 'decls', [])\n  catch\n    call unite#print_source_error(['command returned invalid response.', v:exception], s:source.name)\n  endtry\n\n  return map(l:candidates, \"{\n        \\ 'word': printf('%s :%d :%s', fnamemodify(v:val.filename, ':~:.'), v:val.line, v:val.full),\n        \\ 'kind': 'jump_list',\n        \\ 'action__path': v:val.filename,\n        \\ 'action__line': v:val.line,\n        \\ 'action__col': v:val.col,\n        \\ }\")\nendfunction\n\nfunction! s:source.hooks.on_syntax(args, context) abort\n  syntax match uniteSource__Decls_Filepath /[^:]*\\ze:/ contained containedin=uniteSource__Decls\n  syntax match uniteSource__Decls_Line /\\d\\+\\ze :/ contained containedin=uniteSource__Decls\n  syntax match uniteSource__Decls_WholeFunction /\\vfunc %(\\([^)]+\\) )?[^(]+/ contained containedin=uniteSource__Decls\n  syntax match uniteSource__Decls_Function /\\S\\+\\ze(/ contained containedin=uniteSource__Decls_WholeFunction\n  syntax match uniteSource__Decls_WholeType /type \\S\\+/ contained containedin=uniteSource__Decls\n  syntax match uniteSource__Decls_Type /\\v( )@<=\\S+/ contained containedin=uniteSource__Decls_WholeType\n  highlight default link uniteSource__Decls_Filepath Comment\n  highlight default link uniteSource__Decls_Line LineNr\n  highlight default link uniteSource__Decls_Function Function\n  highlight default link uniteSource__Decls_Type Type\n\n  syntax match uniteSource__Decls_Separator /:/ contained containedin=uniteSource__Decls conceal\n  syntax match uniteSource__Decls_SeparatorFunction /func / contained containedin=uniteSource__Decls_WholeFunction conceal\n  syntax match uniteSource__Decls_SeparatorType /type / contained containedin=uniteSource__Decls_WholeType conceal\nendfunction\n\nlet &cpoptions = s:save_cpo\nunlet s:save_cpo\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "compiler/go.vim",
    "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\" compiler/go.vim: Vim compiler file for Go.\n\nif exists(\"g:current_compiler\")\n  finish\nendif\nlet g:current_compiler = \"go\"\n\n\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nif exists(\":CompilerSet\") != 2\n  command -nargs=* CompilerSet setlocal <args>\nendif\n\nlet s:save_cpo = &cpo\nset cpo-=C\nif filereadable(\"GNUmakefile\") || filereadable(\"makefile\") || filereadable(\"Makefile\")\n  CompilerSet makeprg=make\nelse\n  CompilerSet makeprg=go\\ build\nendif\n\n\" Define the patterns that will be recognized by QuickFix when parsing the\n\" output of Go command that use this errorforamt (when called make, cexpr or\n\" lmake, lexpr). This is the global errorformat, however some command might\n\" use a different output, for those we define them directly and modify the\n\" errorformat ourselves. More information at:\n\" http://vimdoc.sourceforge.net/htmldoc/quickfix.html#errorformat\nCompilerSet errorformat =%-G#\\ %.%#                                 \" Ignore lines beginning with '#' ('# command-line-arguments' line sometimes appears?)\nCompilerSet errorformat+=%-G%.%#panic:\\ %m                          \" Ignore lines containing 'panic: message'\nCompilerSet errorformat+=%Ecan\\'t\\ load\\ package:\\ %m               \" Start of multiline error string is 'can\\'t load package'\nCompilerSet errorformat+=%A%\\\\%%(%[%^:]%\\\\+:\\ %\\\\)%\\\\?%f:%l:%c:\\ %m \" Start of multiline unspecified string is 'filename:linenumber:columnnumber:'\nCompilerSet errorformat+=%A%\\\\%%(%[%^:]%\\\\+:\\ %\\\\)%\\\\?%f:%l:\\ %m    \" Start of multiline unspecified string is 'filename:linenumber:'\nCompilerSet errorformat+=%C%*\\\\s%m                                  \" Continuation of multiline error message is indented\nCompilerSet errorformat+=%-G%.%#                                    \" All lines not matching any of the above patterns are ignored\nlet &cpo = s:save_cpo\nunlet s:save_cpo\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "doc/vim-go.txt",
    "content": "*vim-go.txt* Go development plugin\n*vim-go*\n\n==============================================================================\n#                                                                            #\n#             ##     ## #### ##     ##          ######    #######            #\n#             ##     ##  ##  ###   ###         ##    ##  ##     ##           #\n#             ##     ##  ##  #### ####         ##        ##     ##           #\n#             ##     ##  ##  ## ### ## ####### ##   #### ##     ##           #\n#              ##   ##   ##  ##     ##         ##    ##  ##     ##           #\n#               ## ##    ##  ##     ##         ##    ##  ##     ##           #\n#                ###    #### ##     ##          ######    #######            #\n#                                                                            #\n==============================================================================\nCONTENTS                                                         *go-contents*\n\n  1. Intro........................................|go-intro|\n  2. Install......................................|go-install|\n  3. Commands.....................................|go-commands|\n  4. Mappings.....................................|go-mappings|\n  5. Text Objects.................................|go-text-objects|\n  6. Functions....................................|go-functions|\n  7. Settings.....................................|go-settings|\n  8. Syntax highlighting..........................|go-syntax|\n  9. Debugger.....................................|go-debug|\n 10. FAQ/Troubleshooting..........................|go-troubleshooting|\n 11. Development..................................|go-development|\n 12. Donation.....................................|go-donation|\n 13. Credits......................................|go-credits|\n\n==============================================================================\nINTRO                                                               *go-intro*\n\nGo (golang) support for Vim. vim-go comes with sensible predefined settings\n(e.g. automatic `gofmt` on save), has code completion, snippet support,\nimproved syntax highlighting, go toolchain commands, etc. It is highly\ncustomizable, and individual features can be toggled easily. vim-go leverages\na number of tools developed by the Go community to provide a seamless Vim\nexperience.\n\n  * Compile your package with |:GoBuild|, install it with |:GoInstall| or\n    test it with |:GoTest|. Run a single test with |:GoTestFunc|.\n  * Quickly execute your current file(s) with |:GoRun|.\n  * Improved syntax highlighting and folding.\n  * Debug programs with integrated `delve` support with |:GoDebugStart|.\n  * Code completion support via `gocode` and `gopls`.\n  * `gofmt` or `goimports` on save keeps the cursor position and undo history.\n  * Go to symbol/declaration with |:GoDef|.\n  * Look up documentation with |:GoDoc| or |:GoDocBrowser|.\n  * Easily import packages via |:GoImport|, remove them via |:GoDrop|.\n  * Precise type-safe renaming of identifiers with |:GoRename|.\n  * See which code is covered by tests with |:GoCoverage|.\n  * Add or remove tags on struct fields with |:GoAddTags| and |:GoRemoveTags|.\n  * Call `golangci-lint` with |:GoMetaLinter| to invoke all possible linters\n    (`golint`, `vet`, `errcheck`, `deadcode`, etc.) and put the result in the\n    quickfix or location list.\n  * Lint your code with |:GoLint|, run your code through |:GoVet| to catch\n    static errors, or make sure errors are checked with |:GoErrCheck|.\n  * Advanced source analysis tools utilizing `gopls`, such as |:GoImplements|\n    and |:GoReferrers|.\n  * Integrated and improved snippets, supporting `ultisnips`, `neosnippet`,\n    and `vim-minisnip`.\n  * Share your current code to `go.dev/play` with |:GoPlay|.\n  * On-the-fly information about the word under the cursor. Plug it into your\n    custom Vim function.\n  * Text objects such as \"a function\" (|go-af|) or \"inner function\" (|go-if|).\n  * Most commands are run asynchronously in Neovim and Vim 8. Fully async\n    building and testing.\n  * Integrated with the Neovim terminal, launch |:GoRun| and other Go commands\n    in a terminal buffer.\n  * Switch between `file.go` and `file_test.go` code with |:GoAlternate|.\n  * Supports integration with the Tagbar and ctrlp.vim plugins.\n  * ...and more...\n\n==============================================================================\nINSTALL                                                           *go-install*\n\nvim-go requires at least Vim 8.2.5072 or Neovim 0.4.0. On macOS, if you are\nstill using your system version of Vim, you can use homebrew to keep your\nversion of Vim up-to-date with the following terminal command:\n>\n  brew install vim\n\nThe latest stable release, https://github.com/fatih/vim-go/releases/latest, is\nthe recommended version to use. If you choose to use the master branch\ninstead, please do so with caution; it is a _development_ branch.\n\nvim-go follows the standard runtime path structure and should work with any of\nthe major plugin managers.\n\nFor Pathogen or Vim |packages|, just clone the repo. For other plugin\nmanagers, you may also need to add the lines to your vimrc to execute the\nplugin manager's install command.\n\n*  Vim 8 |packages| >\n\n    git clone https://github.com/fatih/vim-go.git \\\n      ~/.vim/pack/plugins/start/vim-go\n<\n*  https://github.com/tpope/vim-pathogen >\n\n    git clone https://github.com/fatih/vim-go.git ~/.vim/bundle/vim-go\n<\n*  https://github.com/junegunn/vim-plug >\n\n    Plug 'fatih/vim-go', { 'do': ':GoUpdateBinaries' }\n<\n*  https://github.com/Shougo/neobundle.vim >\n\n    NeoBundle 'fatih/vim-go'\n<\n*  https://github.com/gmarik/vundle >\n\n    Plugin 'fatih/vim-go'\n<\n*  Manual (not recommended) >\n\n    Copy all of the files into your `~/.vim` directory\n<\n\nYou will also need to install all the necessary binaries. vim-go makes it easy\nto install all of them by providing a command, |:GoInstallBinaries|, to\n`go install` all the required binaries. The binaries will be installed to\n$GOBIN or $GOPATH/bin (default: $HOME/go/bin). It requires `git`.\n\nDepending on your installation method, you may have to generate the plugin's\n|:helptags| manually (e.g. `:helptags ALL`).\n\nCode completion is enabled by default via 'omnifunc', which you can trigger\nwith |i_CTRL-X_CTRL-O| (`<C-x><C-o>`).\n\nSupported Go plugins~                                         *vim-go-plugins*\n\nThe following plugins are supported for use with vim-go:\n\n* Real-time completion (Vim):\n  https://github.com/Shougo/neocomplete.vim\n\n* Real-time completion (Neovim and Vim 8):\n  https://github.com/Shougo/deoplete.nvim\n\n  Add the following line to your vimrc. This instructs deoplete to use omni\n  completion for Go files.\n\n    call deoplete#custom#option('omni_patterns', { 'go': '[^. *\\t]\\.\\w*' })\n\n* Display source code navigation in a sidebar:\n  https://github.com/majutsushi/tagbar\n\n* Snippets:\n  https://github.com/Shougo/neosnippet.vim or\n  https://github.com/SirVer/ultisnips or\n  https://github.com/joereynolds/vim-minisnip\n\n* Interactive |:GoDecls| and |:GoDeclsDir|:\n  https://github.com/ctrlpvim/ctrlp.vim or\n  https://github.com/junegunn/fzf.vim or\n  https://github.com/Shougo/unite.vim or\n  https://github.com/Shougo/denite.nvim\n\n==============================================================================\nCOMMANDS                                                         *go-commands*\n\n                                                        *:GoReportGitHubIssue*\n:GoReportGitHubIssue\n\n    GoReportGitHubIssue opens the default browser and starts a new bug report\n    with useful system information.\n\n                                                                     *:GoPath*\n:GoPath [path]\n\n    GoPath sets and overrides `GOPATH` with the given {path}. If no {path} is\n    given, it shows the current `GOPATH`. If `\"\"` is given as path, it clears\n    the current `GOPATH` which was set with |:GoPath| and restores `GOPATH`\n    back to the initial value which was sourced when Vim was started.\n\n                                                                   *:GoImport*\n:GoImport[!] [path]\n\n    GoImport ensures that the provided package {path} is imported in the\n    current Go buffer, using proper style and ordering. If {path} is already\n    being imported, an error will be displayed and the buffer will be\n    untouched.\n\n    If [!] is given, it will download the package with `go get`\n\n                                                                 *:GoImportAs*\n:GoImportAs [localname] [path]\n\n    Same as GoImport, but uses a custom local name for the package.\n\n                                                                     *:GoDrop*\n:GoDrop [path]\n\n    Remove the import line for the provided package {path}, if present in the\n    current Go buffer.  If {path} is not being imported, an error will be\n    displayed and the buffer will be untouched.\n\n                                                                     *:GoLint*\n:GoLint! [packages]\n\n    Run the linter for the directory under your current file, or for the given\n    packages.\n\n    If [!] is not given, the first error is jumped to.\n\n                                                                      *:GoDoc*\n:GoDoc [word]\n\n    Open the relevant GoDoc in split window for either the word[s] passed to\n    the command or by default, the word under the cursor.\n\n                                                               *:GoDocBrowser*\n:GoDocBrowser [word]\n\n    Open the relevant GoDoc in browser for either the word[s] passed to the\n    command or by default, the word under the cursor. By default it opens the\n    documentation in `https://pkg.go.dev`. To change it see |'g:go_doc_url'|.\n\n                                                                      *:GoFmt*\n:GoFmt\n\n    Filter the current Go buffer through gofmt.  It tries to preserve cursor\n    position and avoids replacing the buffer with stderr output.\n\n                                                                  *:GoImports*\n:GoImports\n\n    Adjust imports using the setting of `g:go_imports_mode`. Like |:GoFmt|, it\n    tries to preserve cursor position and avoids replacing the buffer with\n    stderr output.\n\n                                                                     *:GoPlay*\n:[range]GoPlay\n\n    Share snippet to `go.dev/play`. If no [range] is given, it shares the\n    whole file, otherwise the selected lines are shared. Snippet URL is copied\n    to system clipboard if Vim is compiled with 'clipboard' or\n    'xterm-clipboard' otherwise it gets yanked into the `\"\"` register.\n\n                                                                      *:GoVet*\n:GoVet[!] [options]\n\n    Run `go vet` for the directory under your current file. Vet examines Go\n    source code and reports suspicious constructs, such as Printf calls whose\n    arguments do not align with the format string. Vet uses heuristics that do\n    not guarantee all reports are genuine problems, but it can find errors not\n    caught by the compilers.\n\n    You may optionally pass any valid go vet flags/options.\n\n    If [!] is not given, the first error is jumped to.\n\n                                                                      *:GoDef*\n:GoDef\ngd\nCTRL-]\ng<C-LeftMouse>\n<C-LeftMouse>\n\n    Go to declaration/definition for the identifier under the cursor. By\n    default the CTRL-] shortcut, the mapping `gd` and <C-LeftMouse>,\n    g<LeftMouse> are enabled to invoke :GoDef for the identifier under the\n    cursor. See |'g:go_def_mapping_enabled'| to disable them. No explicit\n    arguments are supported.\n\n    vim-go also keeps a per-window location stack, roughly analogous to how\n    Vim's internal |tags| functionality works. This is pushed to every time a\n    jump is made using the GoDef functionality. In essence, this is a LIFO\n    list of file locations you have visited with |:GoDef| that is retained to\n    help you navigate software.\n\n    The per-window location stack is shared with |:GoDefType|.\n\n                                                                  *:GoDefType*\n:GoDefType\n\n    Go to type definition for the identifier under the cursor.\n\n    The per-window location stack is shared with |:GoDef|.\n                                                                 *:GoDefStack*\n:GoDefStack [number]\n\n    This command Jumps to a given location in the jumpstack, retaining all\n    other entries. Jumps to non-existent entries will print an informative\n    message, but are otherwise a noop.\n\n    If no argument is given, it will print out an interactive list of all\n    items in the stack. Its output looks like this:\n\n      1 /path/first/file.go|1187 col 16|AddThing func(t *Thing)\n    > 2 /path/thing/thing.go|624 col 19|String() string\n      3 /path/thing/thing.go|744 col 6|func Sprintln(a ...interface{}) string\n\n    This list shows the identifiers that you jumped to and the file and cursor\n    position before that jump.  The older jumps are at the top, the newer at\n    the bottom.\n\n    The '>' points to the active entry.  This entry and any newer entries\n    below it will be replaced if |:GoDef| is done from this location. The\n    CTRL-t and |:GoDefPop| command will jump to the position above the active\n    entry.\n\n    Jumps to non-existent entries will print an informative message, but are\n    otherwise a noop.\n\n                                                            *:GoDefStackClear*\n:GoDefStackClear\n\n    Clears the current stack list and resets it.\n\n                                                                   *:GoDefPop*\n:GoDefPop [count]\nCTRL-t\n\n    Navigate to the [count] earlier entry in the jump stack, retaining the\n    newer entries. If no argument is given, it will jump to the next most\n    recent entry (`:GoDefPop 1`).  If [count] is greater than the number of\n    prior entries, an error will be printed and no jump will be performed.\n\n    If you have used :GoDefPop to jump to an earlier location, and you issue\n    another :GoDef command, the current entry will be replaced, and all newer\n    entries will be removed, effectively resuming the stack at that location.\n\n    By default [count]CTRL-t is enabled to invoke :GoDefPop.  Similarly,\n    hitting CTRL-t without a prior count is equivalent to `:GoDefPop 1`.  See\n    |'g:go_def_mapping_enabled'| to disable this.\n\n                                                                      *:GoRun*\n:GoRun[!] [expand]\n\n    Build and run your current main package. By default all main files for the\n    current file is used. If an argument is passed, [expand] is used as file\n    selector. For example use `:GoRun %` to select the current file only.\n\n    You may optionally pass any valid go run flags/options. For a full list\n    please see `go help run`.\n\n    If [!] is not given, the first error is jumped to.\n\n    If using neovim then `:GoRun` will run in a new terminal according to\n    |'g:go_term_mode'|.\n\n    The working directory will be the directory containing the current buffer.\n\n\n                                                                    *:GoBuild*\n:GoBuild[!] [expand]\n\n    Build your package with `go build`. Errors are populated in the quickfix\n    window. It automatically builds only the files that depend on the current\n    file. `:GoBuild` doesn't produce a result file.\n    Use |:make| to create a result file.\n\n    You may optionally pass any valid go build flags/options. For a full list\n    please see `go help build`. Options are expanded with [expand].\n\n    If [!] is not given, the first error is jumped to.\n\n    If using neovim then this command is fully async, it does not block the\n    UI.\n\n                                                                 *:GoGenerate*\n:GoGenerate[!] [expand]\n\n    Creates or updates your auto-generated source files by running `go\n    generate`.\n\n    You may optionally pass any valid go generate flags/options. For a full\n    list please see `go help generate`. Options are expanded with [expand].\n\n    If [!] is not given, the first error is jumped to.\n\n                                                                     *:GoInfo*\n:GoInfo\n\n    Show type information about the identifier under the cursor. For example\n    putting it above a function call is going to show the full function\n    signature. By default it uses `gopls` to get the type information.\n\n                                                                  *:GoInstall*\n:GoInstall[!] [options]\n\n    Install your package with `go install`.\n\n    You may optionally pass any valid go install flags/options. For a full\n    list please see `go help install`.\n\n    If [!] is not given, the first error is jumped to.\n\n                                                                     *:GoTest*\n:GoTest[!] [expand]\n\n    Run the tests on your _test.go files in your current directory. Errors\n    are populated in the quickfix window.  If an argument is passed, [expand]\n    is used as file selector (useful for cases like `:GoTest ./...`).\n\n    You may optionally pass any valid go test flags/options. For a full list\n    please see `go help test`.\n\n    GoTest times out automatically after 10 seconds. To customize the timeout\n    use |'g:go_test_timeout'|. This feature is disabled if any arguments are\n    passed to the `:GoTest` command.\n\n    If [!] is not given, the first error is jumped to.\n\n    If using neovim `:GoTest` will run in a new terminal or run asynchronously\n    in the background according to |'g:go_term_enabled'|. You can set the mode\n    of the new terminal with |'g:go_term_mode'|.\n\n                                                                 *:GoTestFile*\n:GoTestFile[!] [expand]\n\n    Runs :GoTest, but only on the tests in the current file using 'go test's\n    '-run' flag.\n\n    If [!] is not given, the first error is jumped to.\n\n                                                                 *:GoTestFunc*\n:GoTestFunc[!] [expand]\n\n    Runs :GoTest, but only on the single test function immediate to your\n    cursor using 'go test's '-run' flag.\n\n    Lookup is done starting at the cursor (including that line) moving up till\n    a matching `func Test` pattern is found or top of file is reached. Search\n    will not wrap around when at the top of the file.\n\n    If [!] is not given, the first error is jumped to.\n\n                                                              *:GoTestCompile*\n:GoTestCompile[!] [expand]\n\n    Compile your _test.go files in your current directory. Errors are\n    populated in the quickfix window.  If an argument is passed, [expand] is\n    used as file selector (useful for cases like `:GoTest ./...`). Useful to\n    not run the tests and capture/fix errors before running the tests or to\n    create test binary.\n\n    If [!] is not given, the first error is jumped to.\n\n                                                                 *:GoCoverage*\n:GoCoverage[!] [options]\n\n    Create a coverage profile and annotates the current file's source code. If\n    called again it reruns the tests.\n\n    If [!] is not given, the first error is jumped to.\n\n                                                           *:GoCoverageToggle*\n:GoCoverageToggle[!] [options]\n\n    Create a coverage profile and annotates the current file's source code. If\n    called again clears the annotation (works as a toggle).\n\n    If [!] is not given, the first error is jumped to.\n\n                                                            *:GoCoverageClear*\n:GoCoverageClear [options]\n\n   Clears the coverage annotation.\n\n\n                                                          *:GoCoverageBrowser*\n:GoCoverageBrowser[!] [options]\n\n    Create a coverage profile and open a browser to display the annotated\n    source code of the current package.\n\n    You may optionally pass any valid go test flags/options, such as\n    `-covermode set,count,atomic`. For a full list please see `go help test`.\n\n    If [!] is not given, the first error is jumped to.\n\n                                                          *:GoCoverageOverlay*\n:GoCoverageOverlay file\n\n    Overlay the coverage profile from file.\n\n                                                                 *:GoErrCheck*\n:GoErrCheck! [options]\n\n    Check for unchecked errors in the current package. Errors are populated in\n    the quickfix window.\n\n    You may optionally pass any valid errcheck flags/options. See\n    `errcheck -h` for a full list.\n\n    If [!] is not given, the first error is jumped to.\n\n                                                                    *:GoFiles*\n:GoFiles [source_files]\n\n    Show source files for the current package. The [source_files] specifies\n    which file types to list. See the \"// Source files\" section of\n    `go list -h` for possible values; multiple values are accepted.\n    Command-line completion also works for this command.\n    The default is to use `GoFiles` if no arguments are given.\n\n                                                                     *:GoDeps*\n:GoDeps\n\n    Show dependencies for the current package.\n\n                                                          *:GoInstallBinaries*\n:GoInstallBinaries [binaries]\n\n    Download and install all necessary Go tool binaries such as `godef`,\n    `goimports`, `gopls`, etc. under |'g:go_bin_path'|. If [binaries] is\n    supplied, then only the specified binaries will be installed. The default\n    is to install everything.\n\n    A specific version of a binary can be specified by appending Go's version\n    syntax to the binary name. e.g. `:GoInstallBinaries gopls@v0.9.1`.\n\n    Set |'g:go_get_update'| to disable updating dependencies.\n\n                                                           *:GoUpdateBinaries*\n:GoUpdateBinaries [binaries]\n\n    Download and update previously installed Go tool binaries such as `godef`,\n    `goimports`, `gopls`, etc. under |'g:go_bin_path'|. If [binaries] is\n    supplied, then only the specified binaries will be updated. The default is\n    to update everything.\n\n    A specific version of a binary can be specified by appending Go's version\n    syntax to the binary name. e.g. `:GoUpdateBinaries gopls@v0.9.1`.\n\n    Set |'g:go_get_update'| to disable updating dependencies.\n\n                                                               *:GoImplements*\n:GoImplements\n\n    Show \"implements\" relation for a selected package. A list of interfaces\n    for the type that implements an interface under the cursor (or selected\n    package) is shown in a location list.\n                                                                   *:GoRename*\n:GoRename[!] [to]\n\n    Rename the identifier under the cursor to the desired new name. If no\n    argument is given, a prompt will ask for the desired identifier.\n\n    If [!] is not given, the first error is jumped to.\n\n*:GoCallers*\n:GoCallers\n\n    Show \"callers\" relation for a selected function. A list of possible\n    callers for the selected function under the cursor is shown in a location\n    list.\n\n                                                                *:GoReferrers*\n:GoReferrers\n\n    The referrers query shows the set of identifiers that refer to the same\n    object as does the selected identifier.\n\n                                                                  *:GoSameIds*\n:GoSameIds\n\n    Highlights all identifiers that are equivalent to the identifier under the\n    cursor.\n\n                                                             *:GoSameIdsClear*\n:GoSameIdsClear\n\n    Clears all SameIds highlights from a |:GoSameIds| call.\n\n                                                            *:GoSameIdsToggle*\n:GoSameIdsToggle\n\n    Toggle between |:GoSameIds| and |:GoSameIdsClear|.\n\n                                                        *:GoSameIdsAutoToggle*\n:GoSameIdsAutoToggle\n\n    Enables or disables automatic highlighting of |:GoSameIds| while moving\n    the cursor. This basically toggles the option |'g:go_auto_sameids'|\n    on/off.\n    If enabled it starts highlighting whenever your cursor is staying at the\n    same position for a configurable period of time (see |'g:go_updatetime'|).\n    If disabled it clears and stops automatic highlighting.\n\n                                                               *:GoMetaLinter*\n:GoMetaLinter! [path]\n\n    Calls a metalinter tool and displays all warnings and errors in the\n    |quickfix| window. The linters that are enabled by default vary depending\n    on the value of `g:go_metalinter_command` and can be changed with\n    `g:go_metalinter_enabled`.\n\n    If [!] is not given, the first error is jumped to.\n\n                                                              *:GoDiagnostics*\n:GoDiagnostics! [packages]\n\n    Displays the diagnostics from `gopls` for the given packages in a\n    |quickfix| window. The diagnostics for the current package are displayed\n    when no package is given. The diagnostics for all packages will be\n    displayed when `all` is as an argument.\n\n    Disabled when |'g:go_diagnostics_enabled'| is not set.\n\n    If [!] is not given, the first error is jumped to.\n\n                                                                *:GoBuildTags*\n:GoBuildTags [tags]\n\n    Changes the build tags for various commands. If you have any file that\n    uses a custom build tag, such as `// +build integration`, this command\n    can be used to pass it to all tools that accept tags, such as gopls,\n    go test, etc.\n\n    The build tags are cleared (unset) if `\"\"` is given. If no arguments are\n    given, it prints the current build tags.\n\n                                                                     *:AsmFmt*\n:AsmFmt\n\n    Filter the current Go asm buffer through asmfmt. It tries to preserve\n    cursor position and avoids replacing the buffer with stderr output.\n\n                                                                *:GoAlternate*\n:GoAlternate[!]\n\n    Alternates between the implementation and test code. For example if in\n    main.go, switch to main_test.go. Uses the |'g:go_alternate_mode'| setting\n    as the command to open the file.\n\n    If [!] is given, then it switches to the new file even if it does not\n    exist.\n\n    If you would like to override the traditional commands for alternating,\n    add the following to your .vimrc:\n>\n    augroup go\n      autocmd!\n      autocmd Filetype go\n        \\  command! -bang A call go#alternate#Switch(<bang>0, 'edit')\n        \\| command! -bang AV call go#alternate#Switch(<bang>0, 'vsplit')\n        \\| command! -bang AS call go#alternate#Switch(<bang>0, 'split')\n    augroup END\n<\n\n                                                                    *:GoDecls*\n:GoDecls [file]\n\n    Show all function and type declarations for the current file. If\n    [file] is non empty it parses the given file.\n    Requires `ctrlp.vim` or `fzf`; it will autodetect the plugin if installed,\n    but you can use |'g:go_decls_mode'| to force using one or the other.\n    By default `type` and `func` declarations are shown. This can be changed\n    via |'g:go_decls_includes'|. Also see |unite-decls|, |denite-decls|.\n\n                                                                 *:GoDeclsDir*\n:GoDeclsDir [dir]\n\n    Show all function and type declarations for the current directory. If\n    [dir] is given it parses the given directory.\n\n                                                                 *unite-decls*\n                                                                *denite-decls*\n:Unite decls[:path]\n:Denite decls[:path]\n\n    Only enabled if `unite.vim` or `denite.nvim` is installed. Show\n    declarations for all functions and types on the current file or directory\n    or for [path] if given.\n\n    Note: `denite.nvim` requires NeoVim or Vim 8 with |:python3| enabled.\n>\n    \" show declarations on the parent directory of the current file\n    :Unite decls\n    :Denite decls\n\n    \" show declarations in the file.\n    :Unite decls:foo/bar.go\n    :Denite decls:foo/bar.go\n\n    \" show declarations in the directory \"foo\".\n    :Unite decls:foo\n    :Denite decls:foo\n<\n                                                                     *:GoImpl*\n:GoImpl [receiver] [receiver type] [interface]\n\n    Generates method stubs for implementing an interface. If no arguments are\n    passed it takes the identifier under the cursor to be the receiver and\n    asks for the interface type to be generated. If used with arguments, the\n    receiver name, its type, and the interface needs to be specified. Example\n    usages:\n>\n      :GoImpl f *Foo io.Writer\n      :GoImpl t Type io.ReadWriteCloser\n<\n                                                                  *:GoAddTags*\n:[range]GoAddTags [key],[option] [key1],[option] ...\n\n    Adds field tags for the fields of a struct. If called inside a struct it\n    automatically add field tags with the `json` key and the value\n    automatically generated based on the field name. An error message is given\n    if it's called outside a struct definition or if the file is not correctly\n    formatted.\n\n    If [range] is given only the selected fields will be changed.\n\n    The default `json` can be changed by providing one or more [key]\n    arguments. An example of adding `xml` and `db` would be:\n>\n      :GoAddTags xml db\n<\n    If [option] is passed it'll either add a new tag with an option or will\n    modify existing tags. An example of adding `omitempty` to all `json`\n    fields would be:\n>\n      :GoAddTags json,omitempty\n<\n    You can define a constant value instead of the default field based value.\n    For example the following command will add ``valid:\"1\"`` to all fields.\n>\n      :GoAddTags valid:1\n<\n                                                               *:GoRemoveTags*\n:[range]GoRemoveTags [key],[option] [key1],[option1] ...\n\n    Remove field tags for the fields of a struct. If called inside a struct it\n    automatically remove all field tags. An error message is given if it's\n    called outside a struct definition or if the file is not correctly\n    formatted.\n\n    If [range] is given, only the selected fields will be changed.\n\n    If [key] is given, it will only remove those keys. Example:\n>\n      :GoRemoveTags json\n<\n    If [option] is passed with a [key], it will only remove the options.\n    Example, this will only remove `omitempty` options from fields containing\n    `json`:\n>\n      :GoRemoveTags json,omitempty\n<\n                                                       *:GoAutoTypeInfoToggle*\n:GoAutoTypeInfoToggle\n\n    Toggles |'g:go_auto_type_info'|.\n\n                                                        *:GoFmtAutoSaveToggle*\n:GoFmtAutoSaveToggle\n\n    Toggles |'g:go_fmt_autosave'|.\n\n                                                     *:GoModFmtAutoSaveToggle*\n:GoModFmtAutoSaveToggle\n\n    Toggles |'g:go_mod_fmt_autosave'|.\n\n                                                     *:GoAsmFmtAutoSaveToggle*\n:GoAsmFmtAutoSaveToggle\n\n    Toggles |'g:go_asmfmt_autosave'|.\n\n                                                 *:GoMetaLinterAutoSaveToggle*\n:GoMetaLinterAutoSaveToggle\n\n    Toggles |'g:go_metalinter_autosave'|.\n\n    By default, `golangci-lint` messages will be shown in the |location-list|\n    window. The list to use can be set using |'g:go_list_type_commands'|.\n\n                                                 *:GoTemplateAutoCreateToggle*\n:GoTemplateAutoCreateToggle\n\n    Toggles |'g:go_template_autocreate'|.\n\n                                                               *:GoFillStruct*\n:GoFillStruct\n\n    Use `fillstruct` to fill a struct literal with default values. Existing\n    values (if any) are preserved. The cursor must be on the struct you wish\n    to fill.\n\n    For example:\n>\n      addr := net.Address{Name: \"Ford Prefect\"}\n<\n    Becomes:\n>\n      addr := net.Address{\n        Name: \"Ford Prefect\",\n        Email: \"\",\n      }\n<\n\n                                                                    *:GoIfErr*\n:GoIfErr\n\n    Generate if err != nil { return ... } automatically which infers the types\n    and number of return values.\n\n    For example:\n>\n      func doSomething() (string, error) {\n          f, err := os.Open(\"file\")\n      }\n<\n    Becomes:\n>\n      func doSomething() (string, error) {\n          f, err := os.Open(\"file\")\n          if err != nil {\n              return \"\", err\n          }\n      }\n<\n                                                                  *:GoModFmt*\n:GoModFmt\n\n    Filter the current go.mod buffer through \"go mod edit -fmt\" command.  It\n    tries to preserve cursor position and avoids replacing the buffer with\n    stderr output.\n                                                               *:GoModReload*\n:GoModReload [go.mod]\n\n    Force `gopls` to reload the go.mod file. When not explicitly provided, the\n    go.mod file ambient to the current buffer will be used.\n\n                                                            *:GoAddWorkspace*\n:GoAddWorkspace [dir] ...\n\n    Add directories to the `gopls` workspace.\n\n                                                         *:GoLSPDebugBrowser*\n:GoLSPDebugBrowser\n\n    Open a browser to see gopls debugging information.\n                                                                 *:GoExtract*\n:[range]GoExtract\n\n    Extract the code fragment in the selected line range to a new function and\n    replace the fragment with call to the function.\n\n\n==============================================================================\nMAPPINGS                                                        *go-mappings*\n\nvim-go has several <Plug> keys which can be used to create custom mappings\nFor example, to create a mapping that calls `go run` for the current package,\ncreate a mapping for the `(go-run)`: >\n\n  au FileType go nmap <leader>r <Plug>(go-run)\n\nAs always one is free to create more advanced mappings or functions based with\n|go-commands|. For more information please check out the mappings command\ndocumentation in the |go-commands| section. Available <Plug> keys are:\n\n                                                                    *(go-run)*\n\nCalls `go run` for the current main package.\n\n                                                                *(go-run-tab)*\n\nCalls `go run` for the current file in a new terminal tab.\nThis option is neovim only.\n\n                                                              *(go-run-split)*\n\nCalls `go run` for the current file in a new terminal horizontal split.\nThis option is neovim only.\n\n                                                           *(go-run-vertical)*\n\nCalls `go run` for the current file in a new terminal vertical split.\nThis option is neovim only.\n\n                                                                  *(go-build)*\n\nCalls `go build` for the current package.\n\n                                                               *(go-generate)*\n\nCalls `go generate` for the current package.\n\n                                                                   *(go-info)*\n\nShows type information for the word under the cursor.\n\n                                                                *(go-install)*\n\nCalls `go install` for the current package.\n\n                                                                   *(go-test)*\n\nCalls `go test` for the current package.\n\n                                                              *(go-test-func)*\n\nCalls `go test -run '...'` for the test function immediate to cursor.\n\n                                                              *(go-test-file)*\n\nCalls `go test -run '...'` for all the tests in the current file.\n\n                                                           *(go-test-compile)*\n\nCalls `go test -c` for the current package.\n\n                                                               *(go-coverage)*\n\nCalls `go test -coverprofile-temp.out` for the current package and shows the\ncoverage annotation.\n\n                                                         *(go-coverage-clear)*\n\nClears the coverage annotation.\n\n                                                        *(go-coverage-toggle)*\n\nCalls `go test -coverprofile-temp.out` for the current package and shows the\ncoverage annotation. If run again it acts as a toggle and clears the\nannotation.\n\n                                                                    *(go-fmt)*\n\nFormat the current buffer.\n                                                                *(go-imports)*\n\nAdjust imports for the current buffer.\n\n                                                                   *(go-lint)*\n\nLints for the current package.\n\n                                                                    *(go-vet)*\n\nCalls `go vet` for the current package.\n\n\n                                                                  *(go-files)*\n\nShow source files that depend on the current package.\n\n\n                                                                   *(go-deps)*\n\nShow dependencies for the current package.\n\n                                                                    *(go-doc)*\n\nShow the relevant GoDoc for the word under the cursor in a split window\nleftabove (default mode).\n\n                                                              *(go-doc-split)*\n\nShow the relevant GoDoc for the word under the cursor in a split window.\n\n\n                                                           *(go-doc-vertical)*\n\nShow the relevant GoDoc for the word under the cursor in a vertical split\nwindow.\n\n                                                                *(go-doc-tab)*\n\nShow the relevant GoDoc for the word under the cursor in a tab window.\n\n\n                                                            *(go-doc-browser)*\n\nShow the relevant GoDoc for the word under the cursor in a browser.\n\n                                                                    *(go-def)*\n\nGoto declaration/definition. Results are shown in the current window.\n\n                                                              *(go-def-split)*\n\nGoto declaration/definition. Results are shown in a split window.\nJumps to an existing buffer if |'g:go_def_reuse_buffer'| is enabled.\n\n                                                           *(go-def-vertical)*\n\nGoto declaration/definition. Results are shown in a vertical split window.\nJumps to an existing buffer if |'g:go_def_reuse_buffer'| is enabled.\n\n                                                                *(go-def-tab)*\n\nGoto declaration/definition. Results are shown in a tab window.\nJumps to an existing buffer if |'g:go_def_reuse_buffer'| is enabled.\n\n                                                              *(go-def-type)*\n\nGoto type declaration/definition.  Results are shown in the current window.\nJumps to an existing buffer if |'g:go_def_reuse_buffer'| is enabled.\n\n                                                     *(go-def-type-vertical)*\nGoto type declaration/definition. Results are shown in a vertical split\nwindow.\nJumps to an existing buffer if |'g:go_def_reuse_buffer'| is enabled.\n\n                                                        *(go-def-type-split)*\nGoto type declaration/definition. Results are shown in a split window.\nJumps to an existing buffer if |'g:go_def_reuse_buffer'| is enabled.\n\n                                                          *(go-def-type-tab)*\nGoto type declaration/definition. Results are shown in a tab window.\nJumps to an existing buffer if |'g:go_def_reuse_buffer'| is enabled.\n\n                                                              *(go-def-stack)*\n\nShows the godef tag stack.\n\n                                                        *(go-def-stack-clear)*\n\nResets and clears the tag stack.\n\n                                                                *(go-def-pop)*\n\nJump to previous entry in the tag stack.\n\n                                                             *(go-implements)*\n\nShow the interfaces that the type under the cursor implements.\n\n                                                                 *(go-rename)*\n\nRename the identifier under the cursor to the desired new name.\n\n                                                                *(go-callers)*\n\nShow possible callers of selected function.\n                                                              *(go-referrers)*\n\nShow all refs to entity denoted by selected identifier.\n\n                                                             *(go-metalinter)*\n\nCalls `go-metalinter` for the current directory.\n\n                                                         *(go-alternate-edit)*\n\nAlternates between the implementation and test code in the current window.\n\n                                                        *(go-alternate-split)*\n\nAlternates between the implementation and test code in a new horizontal split.\n\n                                                     *(go-alternate-vertical)*\n\nAlternates between the implementation and test code in a new vertical split.\n\n                                                                 *(go-import)*\n\nCalls `:GoImport` for the current package.\n\n                                                                  *(go-iferr)*\n                                                                 *(go-if-err)*\n\nGenerate if err != nil { return ... } automatically which infers the type and\nnumber of return values.\n\n                                                                *(go-mod-fmt)*\n\nCalls |:GoModFmt| for the current buffer.\n\n                                                            *(go-diagnostics)*\nCalls `:GoDiagnostics`.\n\n                                                             *(go-fillstruct)*\n                                                            *(go-fill-struct)*\nCalls `:GoFillStruct`.\n\n                                                                *(go-extract)*\nCalls `:GoExtract`.\n\n==============================================================================\nTEXT OBJECTS                                                 *go-text-objects*\n\nvim-go comes with several custom |text-objects| that can be used to operate\nupon regions of text. vim-go currently defines the following text objects:\n\n                                               *go-v_af* *go-af*\naf            \"a function\", select contents from a function definition to the\n               closing bracket. If |'g:go_textobj_include_function_doc'| is\n               enabled it also includes the comment doc for a function\n               declaration. This text-object also supports literal functions.\n               If |'g:go_textobj_include_variable'| is enabled it also\n               includes the variable of a function assignment.\n\n                                               *go-v_if* *go-if*\nif            \"inside a function\", select contents of a function,\n              excluding the function definition and the closing bracket. This\n              text-object also supports literal functions.\n\n                                               *go-v_ac* *go-ac*\nac            \"a comment\", select contents of the current comment block.\n\n                                               *go-v_ic* *go-ic*\nic            \"inner comment\", select contents of the current comment block,\n              excluding the start and end comment markers.\n\nvim-go also defines the following text motion objects:\n\n                                               *go-v_]]* *go-]]*\n]]            [count] forward to next function declaration. If\n              |'g:go_textobj_include_function_doc'| is enabled and if you're\n              on a comment, it skips the function which the comment\n              belongs and forwards to the next function declaration.\n\n                                               *go-v_[[* *go-[[*\n[[            [count] backward to previous function declaration.\n\n\n\n==============================================================================\nFUNCTIONS                                                       *go-functions*\n\n                                                        *go#statusline#Show()*\n\nShows the status of a job running asynchronously. Can be used to plug into the\nstatusline. It works to show the status per package instead of per file.\nAssume you have three files open, all belonging to the same package, if the\npackage build (`:GoBuild`) is successful, all statuslines will show `success`,\nif it fails all windows' statuslines will show `failed`.\n\nTo avoid always showing old status information, the status information is\ncleaned for each package after `60` seconds. This can be changed with the\n|'g:go_statusline_duration'| setting.\n\n                                                       *go#complete#GetInfo()*\n\nReturns the description of the identifier under the cursor. Can be used\nto plug into the statusline.\n\n                                                      *go#complete#Complete()*\n\nUses `gopls` for autocompletion. By default, it is hooked up to 'omnifunc'.\n\n                                                   *go#tool#DescribeBalloon()*\n\nSuitable to be used as an expression to show the evaluation balloon. By\ndefault only relevant diagnostics and the type information is shown.\n|'g:go_doc_balloon'| can be used to also include partial documentation. See\n`help balloonexpr`.\n\n==============================================================================\nSETTINGS                                                        *go-settings*\n\n                                                     *'g:go_version_warning'*\n\nEnable warning when using an unsupported version of Vim. By default it is\nenabled.\n>\n  let g:go_version_warning = 1\n<\n\n                                              *'g:go_code_completion_enabled'*\n\nEnable code completion with 'omnifunc'. By default it is enabled.\n>\n  let g:go_code_completion_enabled = 1\n<\n\n                                                *'g:go_code_completion_icase'*\n\nOverride the icase field in 'omnifunc' results. By default it is set to 0.\nSee 'complete-items' for details.\n>\n  let g:go_code_completion_icase = 0\n<\n\n                                                      *'g:go_test_show_name'*\n\nShow the name of each failed test before the errors and logs output by the\ntest. By default it is disabled.\n>\n  let g:go_test_show_name = 0\n<\n\n                                                         *'g:go_test_timeout'*\n\nUse this option to change the test timeout of |:GoTest|. By default it is\nset to 10 seconds . >\n\n  let g:go_test_timeout= '10s'\n<\n                                                 *'g:go_play_browser_command'*\n\nBrowser to use for |:GoPlay|, |:GoDocBrowser|, and |:GoLSPDebugBrowser|. The\nURL must be added with `%URL%`, and it's advisable to include `&` to make sure\nthe shell returns. For example:\n>\n  let g:go_play_browser_command = 'firefox-developer %URL% &'\n<\n\nBy default it tries to find it automatically for the current OS. >\n\n  let g:go_play_browser_command = ''\n<\n                                                    *'g:go_play_open_browser'*\n\nUse this option to open browser after posting the snippet to `go.dev/play`\nwith |:GoPlay|. By default it's enabled. >\n\n  let g:go_play_open_browser = 1\n<\n                                                       *'g:go_auto_type_info'*\n\nUse this option to show the type info (|:GoInfo|) for the word under the\ncursor automatically. Whenever the cursor changes the type info will be\nupdated. By default it's disabled. The delay can be configured with the\n|'g:go_updatetime'| setting.\n>\n  let g:go_auto_type_info = 0\n<\n\n                                                         *'g:go_auto_sameids'*\n\nUse this option to highlight all uses of the identifier under the cursor\n(|:GoSameIds|) automatically. By default it's disabled. The delay can be\nconfigured with the |'g:go_updatetime'| setting.\n>\n  let g:go_auto_sameids = 0\n<\n                                                           *'g:go_updatetime'*\n\nUse this option to configure the delay until it starts some jobs (see\n|'g:go_auto_type_info'|, |'g:go_auto_sameids'|). If set to 0, it uses the\nvalue from 'updatetime'. By default it's set to 800ms.\n>\n  let g:go_updatetime = 800\n<\n                                                        *'g:go_jump_to_error'*\n\nUse this option to enable/disable passing the bang attribute to the mappings\n(e.g. |(go-build)|, |(go-run)|, etc.) and the metalinter on save.  When\nenabled it will jump to the first error automatically (means it will NOT pass\nthe bang attribute to the appropriate command, i.e.: (go-run) -> :GoRun ).\nNote, that calling this doesn't have any effect on calling the commands\nmanually. This setting is only useful for changing the behaviour of our custom\nstatic mappings. By default it's enabled.\n>\n  let g:go_jump_to_error = 1\n<\n                                                         *'g:go_fmt_autosave'*\n\nUse this option to auto |:GoFmt| on save. When both 'g:go_imports_autosave'\nand 'g:go_fmt_autosave' are enabled and both 'g:go_fmt_command' and\n'g:go_imports_mode' are set to `goimports`, `goimports` will be run only once.\nBy default it's enabled.\n>\n  let g:go_fmt_autosave = 1\n<\n                                                          *'g:go_fmt_command'*\n\nUse this option to define which tool is used to format code. Valid options are\n`gofmt`, `goimports`, and `gopls`. By default `gopls` is used.\n>\n  let g:go_fmt_command = 'gopls'\n<\n                                                          *'g:go_fmt_options'*\n\nUse this option to add additional options to the |'g:go_fmt_command'|. Its\nvalue type can be either a string or a dictionary. This is due to backwards\ncompatibility. The string version will be removed in the future so please use\nthe dictionary version. Default is empty.\n>\n  let g:go_fmt_options = ''\n\n  or\n\n  let g:go_fmt_options = {}\n<\nThe dictionary version allows you to define options for multiple binaries:\n>\n  let g:go_fmt_options = {\n    \\ 'gofmt': '-s',\n    \\ 'goimports': '-local mycompany.com',\n    \\ }\n<\n                                                          *'b:go_fmt_options'*\n\nThis option is identical to |'g:go_fmt_options'|, but a buffer-level setting.\nIf present, it's used instead of the global setting. By default it is not set.\n\nAs an example, the following autocmd will configure goimports to put imports\nof packages from the current module in their own group:\n>\n  autocmd FileType go let b:go_fmt_options = {\n    \\ 'goimports': '-local ' .\n      \\ trim(system('{cd '. shellescape(expand('%:h')) .' && go list -m;}')),\n    \\ }\n<\n                                                    *'g:go_fmt_fail_silently'*\n\nUse this option to disable showing a location list when |'g:go_fmt_command'|\nfails. By default the location list is shown. >\n\n  let g:go_fmt_fail_silently = 0\n<\n                                                     *'g:go_fmt_experimental'*\n\nUse this option to enable fmt's experimental mode. This experimental mode is\nsuperior to the current mode as it fully saves the undo history, so undo/redo\ndoesn't break. However, it's slow (creates/deletes a file for every save) and\nit's causing problems on some Vim versions. This has no effect if\n`g:go_fmt_command` is set to `gopls`. By default it's disabled.\n>\n\n  let g:go_fmt_experimental = 0\n\n<\n\n                                                     *'g:go_imports_autosave'*\n\nUse this option to auto |:GoImports| on save. When both\n'g:go_imports_autosave' and 'g:go_fmt_autosave' are enabled and both\n'g:go_fmt_command' and 'g:go_imports_mode' are set to `goimports`, `goimports`\nwill be run only once. By default it's enabled.\n>\n  let g:go_imports_autosave = 1\n<\n                                                         *'g:go_imports_mode'*\n\nUse this option to define which tool is used to adjust imports. Valid options\nare `goimports` and `gopls`. The buffer will not be formatted when this is set\nto `gopls`. By default `gopls` is used.\n>\n\n  let g:go_imports_mode = 'gopls'\n<\n                                                     *'g:go_mod_fmt_autosave'*\n\nUse this option to auto |:GoModFmt| on save. By default it's enabled >\n\n  let g:go_mod_fmt_autosave = 1\n<\n\n                                               *'g:go_doc_keywordprg_enabled'*\n\nUse this option to run `godoc` on words under the cursor with |K|; this will\nnormally run the `man` program, but for Go using `godoc` is more idiomatic. It\nwill not override the 'keywordprg' setting, but will run |:GoDoc|. Default\nis enabled. >\n\n  let g:go_doc_keywordprg_enabled = 1\n<\n                                                           *'g:go_doc_height'*\n\nMaximum height for the GoDoc window created with |:GoDoc|. Default is 20. >\n\n  let g:go_doc_max_height = 20\n<\n                                                         *'g:go_doc_balloon'*\n\nShow GoDoc in balloon. See |go#tool#DescribeBalloon()|. Default is disabled. >\n\n  let g:go_doc_balloon = 0\n<\n\n                                                              *'g:go_doc_url'*\n\ngodoc server URL used when |:GoDocBrowser| is used. Change if you want to use\na private internal service. Default is 'https://pkg.go.dev'.\n>\n  let g:go_doc_url = 'https://pkg.go.dev'\n<\n\n                                                     *'g:go_doc_popup_window'*\n\nUse this option to use the popup-window for |K| and |:GoDoc|, rather than the\n|preview-window|. Default is disabled.\n>\n  let g:go_doc_popup_window = 0\n<\n\n                                                             *'g:go_def_mode'*\n\nUse this option to define the command to be used for |:GoDef|. By default\n`gopls` is used, because it is the fastest. Valid options are `godef` and\n`gopls`.\n>\n  let g:go_def_mode = 'gopls'\n<\n                                                      *'g:go_fillstruct_mode'*\n\nUse this option to define the command to be used for |:GoFillStruct|. By\ndefault `fillstruct` is used. Valid values are `fillstruct` and `gopls`. By\ndefault it is `fillstruct`.\n>\n  let g:go_fillstruct_mode = 'fillstruct'\n<\n                                                  *'g:go_def_mapping_enabled'*\n\nUse this option to enable/disable the default mapping of CTRL-],\n<C-LeftMouse>, g<C-LeftMouse> and (`gd`) for GoDef, CTRL-t for :GoDefPop, and\n(`gD`) for :GoDefType. Disabling it allows you to map something else to these\nkeys or mappings. Default is enabled.\n>\n\n  let g:go_def_mapping_enabled = 1\n<\n                                                     *'g:go_def_reuse_buffer'*\n\nUse this option to jump to an existing buffer for `:GoDef`, `:GoDefType`, and\ntheir mapping variants that cause splits. By default it's disabled. >\n\n  let g:go_def_reuse_buffer = 0\n<\n                                                             *'g:go_bin_path'*\n\nUse this option to change default path for vim-go tools when using\n|:GoInstallBinaries| and |:GoUpdateBinaries|. If not set `go env GOBIN` or\n`$GOPATH/bin` is used. >\n\n  let g:go_bin_path = \"\"\n<\n                                                *'g:go_search_bin_path_first'*\n\nThis option lets |'g:go_bin_path'| (or its default value) take precedence over\n$PATH when invoking a tool command such as |:GoFmt| or |:GoImports|.\n\nEnabling this option ensures that the binaries installed via\n|:GoInstallBinaries| and |:GoUpdateBinaries| are the same ones that are\ninvoked via the tool commands.\n\nBy default it is enabled. >\n\n  let g:go_search_bin_path_first = 1\n<\n                                                       *'g:go_snippet_engine'*\n\nDefine the snippet engine to use. The default is to auto-detect one. Valid\nvalues are:\n\n  automatic      Automatically detect a snippet engine.\n  ultisnips      https://github.com/SirVer/ultisnips\n  neosnippet     https://github.com/Shougo/neosnippet.vim\n  minisnip       https://github.com/joereynolds/vim-minisnip\n                 Note: the original at KeyboardFire/vim-minisnip won't work.\n>\n  let g:go_snippet_engine = \"automatic\"\n<\n                                                           *'g:go_get_update'*\n\nUse this option to disable updating dependencies with |:GoInstallBinaries|. By\ndefault this is enabled.\n>\n  let g:go_get_update = 1\n<\n                                                           *'g:go_build_tags'*\n\nSpace-separated list of build tags passed to the `-tags` flag of tools that\nsupport it.\nThere is also the |:GoBuildTags| convenience command to change or remove build\ntags.\n>\n  let g:go_build_tags = ''\n<\n                                                      *'g:go_textobj_enabled'*\n\nAdds custom text objects. By default it's enabled. >\n\n  let g:go_textobj_enabled = 1\n<\n                                         *'g:go_textobj_include_function_doc'*\n\nConsider the comment above a function to be part of the function when using\nthe `af` text object and `[[` motion. By default it's enabled. >\n\n  let g:go_textobj_include_function_doc = 1\n<\n                                             *'g:go_textobj_include_variable'*\n\nConsider the variable of a function assignment to be part of the anonymous\nfunction when using the `af` text object. By default it's enabled. >\n\n  let g:go_textobj_include_variable = 1\n<\n                                                  *'g:go_metalinter_autosave'*\n\nUse this option to auto |:GoMetaLinter| on save. Only linter messages for\nthe active buffer will be shown.\n\nBy default, `golangci-lint` messages will be shown in the |location-list|\nwindow. The list to use can be set using |'g:go_list_type_commands'|.\n\n By default it's disabled >\n  let g:go_metalinter_autosave = 0\n<\n                                          *'g:go_metalinter_autosave_enabled'*\n\nSpecifies the enabled linters for auto |:GoMetaLinter| on save. When the\nmetalinter is `golangci-lint`, if any are enabled, `--default=none` will be\nsent to the metalinter.\n\nWhen `g:go_metalinter_command` is set to `staticcheck`, the default value is\nan empty list; `staticcheck`'s `-checks` flag will not be used.\n>\n  let g:go_metalinter_autosave_enabled = ['all']\n<\n\nWhen `g:go_metalinter_command` is set to `golangci-lint`, the default value is\n>\n  let g:go_metalinter_autosave_enabled = ['govet', 'revive']\n<\n                                                   *'g:go_metalinter_enabled'*\n\nSpecifies the linters to enable for the |:GoMetaLinter| command. For\n`golangci-lint`, if any are enabled, `--default=none` will be passed to the\nmetalinter.\n\nWhen `g:go_metalinter_command` is set to `staticcheck`, the default value is\nan empty list; `staticcheck`'s `-checks` flag will not be used.\n>\n  let g:go_metalinter_enabled = ['all']\n<\n\nWhen `g:go_metalinter_command` is set to `golangci-lint`, the default value\nis\n>\n  let g:go_metalinter_enabled = ['govet', 'revive', 'errcheck']\n<\n                                                   *'g:go_metalinter_command'*\n\nOverrides the command to be executed when |:GoMetaLinter| is called. By\ndefault it's `staticcheck`. Valid options are `golangci-lint`, `gopls`, and\n`staticcheck`.\n\nWhen the value is `gopls`, users may want to consider setting\n`g:go_gopls_staticcheck`. It can also be used as an advanced setting for users\nwho want to have more control over the metalinter.\n>\n  let g:go_metalinter_command = \"golangci-lint\"\n<\n                                                  *'g:go_metalinter_deadline'*\n\nOverrides the maximum time the linters have to complete. By default it's 5\nseconds.\n\nOnly applies when the metalinter is `golangci-lint`.\n>\n  let g:go_metalinter_deadline = \"5s\"\n<\n                                                          *'g:go_list_height'*\n\nSpecifies the window height for the quickfix and location list windows. The\ndefault value (empty) automatically sets the height to the number of items\n(maximum up to 10 items to prevent large heights). Setting the value\nexplicitly overrides this behavior. For standard Vim behavior, set it to 10.\n>\n  let g:go_list_height = 0\n<\n                                                            *'g:go_list_type'*\n\nSpecifies the type of list to use for command outputs (such as errors from\nbuilds, results from static analysis commands, etc...). The list type for\nspecific commands can be overridden with |'g:go_list_type_commands'|. The\ndefault value (empty) will use the appropriate kind of list for the command\nthat was called. Supported values are \"\", \"quickfix\", and \"locationlist\".\n>\n  let g:go_list_type = \"\"\n<\n\n                                                   *'g:go_list_type_commands'*\n\nSpecifies the type of list to use for command outputs (such as errors from\nbuilds, results from static analysis commands, etc...). When an expected key\nis not present in the dictionary, |'g:go_list_type'| will be used instead.\nSupported keys are \"GoBuild\", \"GoErrCheck\", \"GoFmt\", \"GoModFmt\", \"GoInstall\",\n\"GoLint\", \"GoMetaLinter\", \"GoMetaLinterAutoSave\", \"GoModifyTags\" (used for\nboth :GoAddTags and :GoRemoveTags), \"GoRename\", \"GoRun\", and \"GoTest\".\nSupported values for each command are \"quickfix\" and \"locationlist\".\n>\n  let g:go_list_type_commands = {}\n<\nAs an example, the following settings will change all list types to\n`locationlist` except for `:GoBuild` where `quickfix` is used:\n>\n  let g:go_list_type = \"locationlist\"\n  let g:go_list_type_commands = {\"GoBuild\": \"quickfix\"}\n<\n\n                                                       *'g:go_list_autoclose'*\n\nSpecifies whether the quickfix/location list should be closed automatically\nin the absence of errors.  The default value is 1.\nIf you prefer to keep a long running error window open, you can disable\nthis by setting the value to 0.\n>\n  let g:go_list_autoclose = 1\n<\n                                                      *'g:go_asmfmt_autosave'*\n\nUse this option to auto |:AsmFmt| on save. By default it's disabled. >\n\n  let g:go_asmfmt_autosave = 0\n<\n                                                            *'g:go_term_mode'*\n\nThe default command used to open a new terminal for go commands such as\n|:GoRun|.  The default is `:vsplit`.\n\nApplicable to Neovim and Vim with `terminal` feature only.\n>\n  let g:go_term_mode = \"vsplit\"\n<\n                                                          *'g:go_term_reuse'*\n\nReuse the terminal window when |'g:go_term_enabled'| is set. By default it's\ndisabled.\n>\n  let g:go_term_reuse = 0\n<\n                                                          *'g:go_term_height'*\n                                                           *'g:go_term_width'*\n\nControls the height and width of a terminal split, respectively. By default\nthese are not set, meaning that the height and width are set automatically by\nthe editor. The height only applies to a horizontal split and width only\napplies to a vertical split.\n\nApplicable to Neovim and Vim with `terminal` feature only.\n\nFor example here is how to set each to 30.\n>\n  let g:go_term_height = 30\n  let g:go_term_width = 30\n<\n                                                         *'g:go_term_enabled'*\n\nCauses some types of jobs to run inside a new terminal according to\n|'g:go_term_mode'|. By default it is disabled.\n\nApplicable to Neovim and Vim with `terminal` feature only.\n>\n  let g:go_term_enabled = 0\n<\n                                                   *'g:go_term_close_on_exit'*\n\nCloses the terminal after the command run in it exits when the command fails.\nBy default it is enabled.\n\nApplicable to Neovim and Vim with `terminal` feature only.\n\n>\n  let g:go_term_close_on_exit = 1\n<\n                                                       *'g:go_alternate_mode'*\n\nSpecifies the command that |:GoAlternate| uses to open the alternate file.  By\ndefault it is set to edit.\n>\n  let g:go_alternate_mode = \"edit\"\n<\n                                                       *'g:go_rename_command'*\n\nUse this option to define which tool is used to rename. By default `gopls`\nis used. Valid options are `gopls`, `gopls rename`, and `gorename`.\n>\n  let g:go_rename_command = 'gopls'\n<\n                                                     *'g:go_gorename_prefill'*\n\nExpression to prefill the new identifier when using |:GoRename| without any\narguments. Use an empty string if you don't want to prefill anything. By\ndefault it converts the identifier to camel case but preserves the\ncapitalisation of the first letter to ensure that the exported state stays the\nsame.\n>\n  let g:go_gorename_prefill = 'expand(\"<cword>\") =~# \"^[A-Z]\"' .\n        \\ '? go#util#pascalcase(expand(\"<cword>\"))' .\n        \\ ': go#util#camelcase(expand(\"<cword>\"))'\n<\n\n                                                        *'g:go_gopls_enabled'*\n\nSpecifies whether `gopls` can be used by vim-go.\n\nCompletion will not work when gopls is disabled and other configuration\noptions may also need to be adjusted.\n\nBy default gopls is enabled.\n\n>\n  let g:go_gopls_enabled = 1\n<\n\n                                                        *'g:go_gopls_options'*\n\nThe commandline arguments to pass to gopls.\n\nBy default, it is `['-remote=auto']`.\n>\n  let g:go_gopls_options = ['-remote=auto']\n<\n\n                                                       *'g:go_gopls_analyses'*\n\nThe analyses settings for `gopls`.\n\nThe expected value is either `v:null` or a dictionary. The dictionary will be\nprovided to `gopls` via json-rpc, so dictionary values need to be of the\nappropriate type for Vim to convert to JSON (e.g. truthy dictionary values\nshould be `v:true` or `v:false`). By default, it is `v:null`.\n>\n  let g:go_gopls_analyses = v:null\n<\n\n                                            *'g:go_gopls_complete_unimported'*\n\nSpecifies whether `gopls` should include suggestions from unimported packages.\n\nWhen it is `v:null`, `gopls`' default will be used. By default it is `v:null`.\n>\n  let g:go_gopls_complete_unimported = v:null\n<\n\n                                                *'g:go_gopls_deep_completion'*\n\nSpecifies whether `gopls` should use deep completion.\n\nWhen it is `v:null`, `gopls`' default will be used. By default it is `v:null`.\n>\n  let g:go_gopls_deep_completion = v:null\n<\n\n                                                       *'g:go_gopls_matcher'*\n\nSpecifies how `gopls` should match for completions.\n\nValid values are `v:null`, `fuzzy`, and `caseSensitive`. When it is `v:null`,\n`gopls`' default will be used. By default it is `v:null`.\n>\n  let g:go_gopls_matcher = v:null\n<\n\n                                                   *'g:go_gopls_staticcheck'*\n\nSpecifies whether `gopls` should run staticcheck checks.\n\nWhen it is `v:null`, `gopls`' default will be used. By default it is `v:null`.\n>\n  let g:go_gopls_staticcheck = v:null\n<\n\n                                               *'g:go_gopls_use_placeholders'*\n\nSpecifies whether `gopls` can provide placeholders for function parameters and\nstruct fields. When set, completion items will be treated as anonymous\nsnippets if UltiSnips is installed and configured to be used as\n|'g:go_snippet_engine'|.\n\nWhen it is `v:null`, `gopls`' default will be used. By default it is `v:null`.\n>\n  let g:go_gopls_use_placeholders = v:null\n<\n\n                                                   *'g:go_gopls_temp_modfile'*\n\nSpecifies whether `gopls` should use a temp modfile and suggest edits rather\nthan modifying the ambient go.mod file.\n\nWhen it is `v:null`, `gopls`' default will be used. By default it is `v:null`.\n>\n  let g:go_gopls_temp_modfile = v:null\n<\n\n                                                         *'g:go_gopls_local'*\n\nSpecifies the prefix for imports that `gopls` should group separately.\n\nThe value can either be a string or a dictionary. When it is a string, all\nworkspaces will use the same value. When it is a dictionary, the key should be\nthe absolute path of the workspace and the value is the prefix to use for\nlocal imports within that workspace.\n\nWhen it is `v:null`, `gopls`' default will be used. By default it is `v:null`.\n>\n  let g:go_gopls_local = v:null\n<\n\n                                                       *'g:go_gopls_gofumpt'*\n\nSpecifies whether `gopls` should use `gofumpt` for formatting.\n\nWhen it is `v:null`, `gopls`' default will be used. By default it is `v:null`.\n>\n  let g:go_gopls_gofumpt = v:null\n<\n\n                                                      *'g:go_gopls_settings'*\n\nSpecifies `gopls` workspace settings for `gopls` that are not yet officially\nsupported by vim-go.\n\nAny value in the dictionary will be overridden by values provided in the\nspecific options supported by vim-go (e.g.  g:go_gopls_staticcheck) or\nsettings statically configured by vim-go to ensure expected behavior. By\ndefault it is `v:null`.\n>\n  let g:go_gopls_settings = v:null\n<\n                                                 *'g:go_diagnostics_enabled'*\n\nDeprecated. See `'g:go_diagnostics_level'`. Specifies whether `gopls`\ndiagnostics are enabled. Only the diagnostics for the current buffer will be\nprocessed when it is not set; all others will be ignored. By default it is\ndisabled.\n>\n  let g:go_diagnostics_enabled = 0\n<\n                                                  *'g:go_diagnostics_level'*\n\nSpecifies the `gopls` diagnostics level. Valid values are 0, 1, and 2. 0\nignores `gopls` diagnostics, 1 is for errors only, and 2 is for errors and\nwarnings. By default it is 0.\n>\n  let g:go_diagnostics_level = 0\n<\n\n                                                  *'g:go_template_autocreate'*\n\nWhen a new Go file is created, vim-go automatically fills the buffer content\nwith a Go code template. By default, the templates under the `templates`\nfolder are used.  This can be changed with the |'g:go_template_file'| and\n|'g:go_template_test_file'| settings to either use a different file in the\nsame `templates` folder, or to use a file stored elsewhere.\n\nIf the new file is created in an already prepopulated package (with other Go\nfiles), in this case a Go code template with only the Go package declaration\n(which is automatically determined according to the current package) is added.\n\nTo always use the package name instead of the template, enable the\n|'g:go_template_use_pkg'| setting.\n\nBy default it is enabled.\n>\n  let g:go_template_autocreate = 1\n<\n                                                        *'g:go_template_file'*\n\nSpecifies either the file under the `templates` folder that is used if a new\nGo file is created. Checkout |'g:go_template_autocreate'| for more info. By\ndefault the `hello_world.go` file is used.\n\nThis variable can be set to an absolute path, so the template files don't have\nto be stored inside the vim-go directory structure. Useful when you want to\nuse different templates for different projects.\n>\n  let g:go_template_file = \"hello_world.go\"\n<\n                                                   *'g:go_template_test_file'*\n\nLike with |'g:go_template_file'|, this specifies the file to use for test\ntemplates. The template file should be under the `templates` folder,\nalternatively absolute paths can be used, too. Checkout\n|'g:go_template_autocreate'| for more info. By default, the\n`hello_world_test.go` file is used.\n>\n  let g:go_template_test_file = \"hello_world_test.go\"\n<\n                                                     *'g:go_template_use_pkg'*\n\nSpecifies that, rather than using a template, the package name is used if a\nnew Go file is created. Checkout |'g:go_template_autocreate'| for more info.\nBy default the template file specified by |'g:go_template_file'| is used.\n>\n  let g:go_template_use_pkg = 0\n<\n                                                       *'g:go_decls_includes'*\n\nOnly useful if `ctrlp.vim`, `unite.vim`, `denite.nvim` or `fzf` are installed.\nThis sets which declarations to show for |:GoDecls| (`ctrp.vim`),\n|unite-decls| (`unite.vim`) and |denite-decls| (`denite.nvim`).  It is a Comma\ndelimited list.  Possible options are: {func,type}.  The default is: >\n\n      let g:go_decls_includes = 'func,type'\n<\n                                                       *'g:go_decls_mode'*\n\nDefine the tool to be used for |:GoDecls|. Valid options are `ctrlp.vim`,\n`fzf`, or an empty string; in which case it will try to autodetect either\n`ctrlp.vim` or `fzf`.\n>\n      let g:go_decls_mode = ''\n<\n                                                    *'g:go_echo_command_info'*\n\nEchoes information about various Go commands, such as `:GoBuild`, `:GoTest`,\n`:GoCoverage`, etc... Useful to disable if you use the statusline integration,\ni.e.: |go#statusline#Show()|. By default it's enabled\n>\n      let g:go_echo_command_info = 1\n<\n                                                       *'g:go_echo_go_info'*\n\nUse this option to show the identifier information when code completion is\ndone. By default it's enabled.\n>\n      let g:go_echo_go_info = 1\n<\nPlease note that 'noshowmode' must be set for this feature to work correctly.\n\n                                                  *'g:go_statusline_duration'*\n\nSpecifies the duration of statusline information being showed per package. By\ndefault it's 60 seconds. Must be in milliseconds.\n>\n      let g:go_statusline_duration = 60000\n<\n                                                   *'g:go_addtags_transform'*\n\nSets the `transform` option for `gomodifytags` when using |:GoAddTags| or if\nit's being used for snippet expansion of single fields.  Possible options are:\n`snakecase`, `camelcase`, `lispcase`, `pascalcase`, `keep`. For the following\ncase, if `snakecase` is used the field will be transformed to:\n>\n  type T struct {\n    FooBarQuz string `json:\"foo_bar_quz\"`\n  }\n<\n\nIf \"camelcase\" is used:\n>\n  type T struct {\n    FooBarQuz string `json:\"fooBarQuz\"`\n  }\n<\nBy default \"snakecase\" is used. Current values are: [\"snakecase\",\n\"camelcase\", \"lispcase\", \"pascalcase\", \"keep\"].\n>\n      let g:go_addtags_transform = 'snakecase'\n<\n                                              *'g:go_addtags_skip_unexported'*\n\nSets the `skip-unexported` option for `gomodifytags` when using |:GoAddTags|.\nIf set it will prevent `gomodifytags` from adding tags to unexported fields:\n>\n  type T struct {\n    FooBar string `json:\"foo_bar\"`\n    quz    string\n  }\n<\nBy default it is disabled.\n>\n      let g:go_addtags_skip_unexported = 0\n<\n                                                                *'g:go_debug'*\n\nA list of options to debug; useful for development and/or reporting bugs.\n\nCurrently accepted values:\n\n  shell-commands     Echo all shell commands that vim-go runs.\n  debugger-state     Expose debugger state in 'g:go_debug_diag'.\n  debugger-commands  Echo communication between vim-go and `dlv`; requests and\n                     responses are recorded in `g:go_debug_commands`.\n  lsp                Echo communication between vim-go and `gopls`. All\n                     communication is shown in a dedicated window. When\n                     enabled before gopls is started, |:GoLSPDebugBrowser| can\n                     be used to open a browser window to help debug gopls.\n>\n      let g:go_debug = []\n<\n\n==============================================================================\nSYNTAX HIGHLIGHTING                                 *ft-go-syntax* *go-syntax*\n\nvim-go comes with an enhanced version of Vim's Go syntax highlighting. It\ncomes with a number of features, most of which are disabled by default.\n\nThe recommended settings are the default values. If you're experiencing\nslowdowns in Go files and you enabled some of these options then try disabling\nthem; some can be resource intensive.\n\n                                                          *'g:go_fold_enable'*\n\nControl syntax-based folding which takes effect when 'foldmethod' is set to\n`syntax`.\nYou can enable specific fold regions by setting an array. Possible values are:\n\n block                `{` .. `}` blocks.\n import               `import` block.\n varconst             `var` and `const` blocks.\n package_comment      The package comment.\n comment              Any comment that is not the package comment.\n\nBy default all except \"comment\" are enabled:\n>\n  let g:go_fold_enable = ['block', 'import', 'varconst', 'package_comment']\n<\nEnable folding of only imports:\n>\n  let g:go_fold_enable = ['import']\n<\nDisable everything (same as not setting 'foldmethod' to `syntax`):\n>\n  let g:go_fold_enable = []\n<\n                                     *'g:go_highlight_array_whitespace_error'*\n\nHighlight white space after `[]`. >\n\n  let g:go_highlight_array_whitespace_error = 0\n<\n                                      *'g:go_highlight_chan_whitespace_error'*\n\nHighlight white space around the receive operator (`<-`) that doesn't follow\nthe standard style. >\n\n  let g:go_highlight_chan_whitespace_error = 0\n<\n                                                *'g:go_highlight_extra_types'*\n\nHighlight commonly used library types (`io.Reader`, etc.). >\n\n  let g:go_highlight_extra_types = 0\n<\n                                            *'g:go_highlight_space_tab_error'*\n\nHighlight instances of tabs following spaces. >\n\n  let g:go_highlight_space_tab_error = 0\n<\n                                  *'g:go_highlight_trailing_whitespace_error'*\n\nHighlight trailing white space. >\n\n  let g:go_highlight_trailing_whitespace_error = 0\n<\n                                                  *'g:go_highlight_operators'*\n\nHighlight operators such as `:=` , `==`, `-=`, etc.\n>\n  let g:go_highlight_operators = 0\n<\n                                                  *'g:go_highlight_functions'*\n\nHighlight function and method declarations.\n>\n  let g:go_highlight_functions = 0\n<\n                                       *'g:go_highlight_function_parameters'*\n\nHighlight the variable names in parameters (including named return parameters)\nin function declarations. Setting this implies the functionality from\n|'g:go_highlight_functions'|.\n>\n  let g:go_highlight_function_parameters = 0\n<\n                                             *'g:go_highlight_function_calls'*\n\nHighlight function and method calls.\n>\n  let g:go_highlight_function_calls = 0\n<\n                                                      *'g:go_highlight_types'*\n\nHighlight struct and interface names.\n>\n  let g:go_highlight_types = 0\n<\n                                                     *'g:go_highlight_fields'*\n\nHighlight struct field names.\n>\n  let g:go_highlight_fields = 0\n<\n                                          *'g:go_highlight_build_constraints'*\n\nHighlights build constraints.\n>\n  let g:go_highlight_build_constraints = 0\n<\n                                              *'g:go_highlight_generate_tags'*\n\nHighlight go:generate directives.\n>\n  let g:go_highlight_generate_tags = 0\n<\n                                          *'g:go_highlight_string_spellcheck'*\n\nHighlight spelling errors in strings when |spell| is enabled.\n>\n  let g:go_highlight_string_spellcheck = 1\n<\n                                             *'g:go_highlight_format_strings'*\n\nHighlight printf-style formatting verbs inside string literals.\n>\n  let g:go_highlight_format_strings = 1\n<\n                                      *'g:go_highlight_variable_declarations'*\n\nHighlight variable names in variable declarations (`x` in `x :=`).\n>\n  let g:go_highlight_variable_declarations = 0\n<\n                                       *'g:go_highlight_variable_assignments'*\n\nHighlight variable names in variable assignments (`x` in `x =`).\n>\n  let g:go_highlight_variable_assignments = 0\n<\n                                          *'g:go_highlight_diagnostic_errors'*\n\nHighlight diagnostic errors.\n>\n  let g:go_highlight_diagnostic_errors = 1\n<\n                                        *'g:go_highlight_diagnostic_warnings'*\n\nHighlight diagnostic warnings.\n>\n  let g:go_highlight_diagnostic_warnings = 1\n<\n\n==============================================================================\n                                           *gohtmltmpl* *ft-gohtmltmpl-syntax*\n                                           *gotexttmpl* *ft-gotexttmpl-syntax*\nGo template syntax~\n\nThe `gotexttmpl` 'filetype' provides syntax highlighting and indentation for\nGo's `text/template` package.\n\nThe `gohtmltmpl` filetype is for use with the `html/template` package and is\nidentical to `gotexttmpl` except that it will also load the standard `html`\nfiletype.\n\nThe `gohtmltmpl` filetype is automatically set for `*.tmpl` files; the\n`gotexttmpl` is never automatically set and needs to be set manually.\n\n==============================================================================\n                                                    *gomod* *ft-gomod-syntax*\ngo.mod file syntax~\n\nThe `gomod` 'filetype' provides syntax highlighting for Go's module file\n`go.mod`\n\n\n==============================================================================\nDEBUGGER                                                            *go-debug*\n\nVim-go comes with a special \"debugger mode\". This starts a `dlv` process in\nthe background and provides various commands to communicate with it.\n\nThis debugger is similar to Visual Studio or Eclipse and has the following\nfeatures:\n\n  * Show stack trace and jumps.\n  * List local variables.\n  * List function arguments.\n  * Expand values of struct or array/slice.\n  * Show balloon on the symbol.\n  * Show output of stdout/stderr.\n  * Toggle breakpoint.\n  * Stack operation continue/next/step out.\n\nThis feature requires either Vim 8.0.0087 or newer with the |+job| feature or\nNeovim. This feature also requires Delve 1.0.0 or newer, and it is\nrecommended to use Go 1.10 or newer, as its new caching will speed up\nrecompiles.\n\n                                                              *go-debug-intro*\nGETTING STARTED WITH THE DEBUGGER~\n\nUse |:GoDebugStart| or |:GoDebugTest| to start the debugger. The first\nargument is the package name, and any arguments after that will be passed on\nto the program; for example:\n>\n    :GoDebugStart . -someflag value\n<\nThis may take a few seconds. After the code is compiled you'll see three new\nwindows: the stack trace on left side, the variable list on the bottom-left,\nand program output at the bottom.\n\nYou can add breakpoints with |:GoDebugBreakpoint| (<F9>) and run your program\nwith |:GoDebugContinue| (<F5>).\n\nThe program will halt on the breakpoint, at which point you can inspect the\nprogram state. You can go to the next line with |:GoDebugNext| (<F10>) or step\nin with |:GoDebugStep| (<F11>).\n\nThe program can also be halted with `:GoDebugHalt` (<F8>).\n\nThe variable window in the bottom left (`GODEBUG_VARIABLES`) will display all\nlocal variables. Struct values are displayed as `{...}`, array/slices as\n`[4]`. Use <CR> on the variable name to expand the values.\n\nThe `GODEBUG_OUTPUT` window displays output from the program and the Delve\ndebugger.\n\nThe `GODEBUG_STACKTRACE` window can be used to jump to different places in the\ncall stack.\n\nWhen you're done use |:GoDebugStop| to close the debugging windows and halt\nthe `dlv` process, or |:GoDebugRestart| to recompile the code.\n\n                                                           *go-debug-commands*\nDEBUGGER COMMANDS~\n\nOnly the commands to start the client or toggle breakpoints are available by\ndefault. |:GoDebugContinue| becomes available after starting the client.  The\nrest of the commands and mappings become available after executing\n|:GoDebugContinue|.\n\n                                                               *:GoDebugStart*\n:GoDebugStart [pkg] [program-args]\n\n    Start the debug mode for [pkg]; this does several things:\n\n      * Setup the debug windows according to |'g:go_debug_windows'|.\n      * Make the `:GoDebug*` commands and `(go-debug-*)` mappings available.\n\n    The directory of the current buffer is used if [pkg] is empty. Any other\n    arguments will be passed to the program.\n\n    Use |:GoDebugStop| to stop `dlv` and exit debugging mode.\n\n                                                             *:GoDebugAttach*\n:GoDebugAttach pid\n\n    Start the debug mode for pid; this does several things:\n\n      * Setup the debug windows according to |'g:go_debug_windows'|.\n      * Make the `:GoDebug*` commands and `(go-debug-*)` mappings available.\n\n    Use |:GoDebugStop| to stop `dlv` and exit debugging mode.\n\n                                                             *:GoDebugConnect*\n:GoDebugConnect [addr]\n\n  Connect to a running instance of delve. If addr is not supplied, then\n  |'g:go_debug_address'| will be used.\n\n  The debug windows will be setup according to |'g:go_debug_windows'|, and the\n  `:GoDebug*` commands and `(go-debug-*)` mappings will be available.\n\n  Use |:GoDebugStop| to exit debugging mode.\n\n\n                                                                *:GoDebugTest*\n:GoDebugTest [pkg] [program-args]\n\n    Behaves the same as |:GoDebugStart| but runs `dlv test` instead of\n    `dlv debug` so you can debug tests.\n\n    Use `-test.flag` to pass flags to `go test` when debugging a test; for\n    example `-test.v` or `-test.run TestFoo`\n\n                                                            *:GoDebugTestFunc*\n:GoDebugTestFunc [expand]\n\n    Behaves the same as |:GoDebugTest| and implicitly adds `-test.run` to run\n    the nearest test or example function (i.e. the nearest function\n    declaration that matches `func Test` or `func Example`) at or previous to\n    the cursor.  Search will not wrap around when at the top of the file.\n\n                                                             *:GoDebugRestart*\n:GoDebugRestart\n\n    Stop the program (if running) and restart `dlv` to recompile the package.\n    The current window layout and breakpoints will be left intact.\n\n                                                                *:GoDebugHalt*\n                                                             *(go-debug-halt)*\n:GoDebugHalt\n\n    Halt the program.\n\n    Mapped to <F8> by default.\n\n                                                                *:GoDebugStop*\n                                                             *(go-debug-stop)*\n:GoDebugStop\n\n    Stop `dlv` and remove all debug-specific commands, mappings, and windows.\n\n                                                          *:GoDebugBreakpoint*\n                                                       *(go-debug-breakpoint)*\n:GoDebugBreakpoint [linenr]\n\n    Toggle breakpoint for the [linenr]. [linenr] defaults to the current line\n    if it is omitted. A line with a breakpoint will have the\n    {godebugbreakpoint} |:sign| placed on it. The line the program is\n    currently halted on will have the {godebugcurline} sign.\n\n                                    *hl-GoDebugCurrent* *hl-GoDebugBreakpoint*\n    A line with a breakpoint will be highlighted with the {GoDebugBreakpoint}\n    group; the line the program is currently halted on will be highlighted\n    with {GoDebugCurrent}.\n\n    Mapped to <F9> by default.\n\n                                                            *:GoDebugContinue*\n                                                         *(go-debug-continue)*\n:GoDebugContinue\n\n    Continue execution until breakpoint or program termination. It will start\n    the program if it hasn't been started yet.\n\n    Mapped to <F5> by default.\n\n                                                                *:GoDebugNext*\n                                                             *(go-debug-next)*\n:GoDebugNext\n\n    Advance execution by one line, also called \"step over\" by some other\n    debuggers.\n\n    Mapped to <F10> by default.\n\n                                                                *:GoDebugStep*\n                                                             *(go-debug-step)*\n:GoDebugStep\n\n    Advance execution by one step, stopping at the next line of code that will\n    be executed (regardless of location).\n\n    Mapped to <F11> by default.\n\n                                                             *:GoDebugStepOut*\n                                                          *(go-debug-stepout)*\n\n:GoDebugStepOut\n\n    Run all the code in the current function and halt when the function\n    returns (\"step out of the current function\").\n\n                                                                 *:GoDebugSet*\n:GoDebugSet {var} {value}\n\n    Set the variable {var} to {value}. Example:\n>\n      :GoDebugSet truth 42\n<\n    This only works for `float`, `int` and variants, `uint` and variants,\n    `bool`, and pointers (this is a `delve` limitation, not a vim-go\n    limitation).\n\n                                                               *:GoDebugPrint*\n                                                            *(go-debug-print)*\n:GoDebugPrint {expr}\n\n    Print the result of a Go expression.\n>\n    :GoDebugPrint truth == 42\n    truth == 42 true\n<\n    Mapped to <F6> by default, which will evaluate the <cword> under the\n    cursor.\n\n                                                           *go-debug-settings*\nDEBUGGER SETTINGS~\n\n                                                        *'g:go_debug_windows'*\n\nControls the window layout for debugging mode. This is a |dict| with four\npossible keys: \"vars\", \"stack\", \"goroutines\", and \"out\"; each of the new\nwindows will be created in that order with the commands in the value. The\ncurrent window is made the only window before creating the debug windows\nunless `g:go_debug_windows` is empty. See also |'g:go_debug_preserve_layout'|.\n\nA window will not be created if a key is missing or empty.\n\nDefaults:\n>\n  let g:go_debug_windows = {\n            \\ 'vars':       'leftabove 30vnew',\n            \\ 'stack':      'leftabove 20new',\n            \\ 'goroutines': 'botright 10new',\n            \\ 'out':        'botright 5new',\n  \\ }\n<\nShow only variables on the right-hand side: >\n\n  let g:go_debug_windows = {\n        \\ 'vars':  'rightbelow 60vnew',\n  \\ }\n<\n\n                                                *'g:go_debug_preserve_layout'*\n\nPreserve window layout in debugging mode. This setting is considered only when\n|'g:go_debug_windows'| is not empty.\n>\n  let g:go_debug_preserve_layout = 0\n<\n                                               *'g:go_debug_substitute_paths'*\n\nSubstitute paths in the debugger. This is a list of lists where each element\nis a list wherein the remote path (the from side) is the first element and the\nlocal path (the to side) is the second element. These are necessary when the\nbinary being debugged was not built from the same location that its source\nresides locally. By default it is empty.\n\n>\n  let g:go_debug_substitute_paths = [['/compiled/from', '/cloned/to']]\n<\n                                                       *'g:go_debug_mappings'*\n\nContains custom key mapping information to customize the active mappings\nwhen debugging.\n\nOnly the customizations desired need to be provided; the debugger will use its\ndefault key mappings for any mapping not defined here.\n\nThis value should be a dictionary whose keys are the plugin mapping commands\n(e.g.  `(go-debug-continue)`). The values are dictionaries with two keys:\n`key` and `attributes`.\n\n`key` is expected to be the key to map (i.e. it's the `lhs` in a mapping).\n`key` can be empty or missing to prevent a key mapping from being applied for\none of the named mappings.\n\n`arguments` is the string of `map-arguments` for the mapping (e.g.\n`<nowait>`).\n\nThe first item must be the `lhs` to use for the mapping. The optional\nsecond item is for `:map-arguments`. All mappings will always be `:map-local`,\nso there is never a need to include `\"<buffer>\"` in the arguments.\n>\n  let g:go_debug_mappings = {\n    \\ '(go-debug-continue)': {'key': 'c', 'arguments': '<nowait>'},\n    \\ '(go-debug-stop)': {'key': 'q'},\n    \\ '(go-debug-next)': {'key': 'n', 'arguments': '<nowait>'},\n    \\ '(go-debug-step)': {'key': 's'},\n  \\}\n<\n\nDefaults are equivalent to:\n>\n  let g:go_debug_mappings = {\n     \\ '(go-debug-continue)':   {'key': '<F5>'},\n     \\ '(go-debug-print)':      {'key': '<F6>'},\n     \\ '(go-debug-breakpoint)': {'key': '<F9>'},\n     \\ '(go-debug-next)':       {'key': '<F10>'},\n     \\ '(go-debug-step)':       {'key': '<F11>'},\n     \\ '(go-debug-halt)':       {'key': '<F8>'},\n  \\ }\n<\n\nYour user specified settings will be merged with the defaults.\n\n                                                        *'g:go_debug_address'*\n\nServer address `dlv` will listen on; must be in `hostname:port` format.\nDefaults to `127.0.0.1:8181`:\n>\n  let g:go_debug_address = '127.0.0.1:8181'\n<\n\n                                                     *'g:go_debug_log_output'*\n\nSpecifies log output options for `dlv`. Value should be a single string of\ncomma-separated options suitable for passing to `dlv`.  An empty string (`''`)\nwill suppress logging entirely.  Default: `'debugger,rpc'`:\n>\n  let g:go_debug_log_output = 'debugger,rpc'\n<\n\n                                                     *'g:go_highlight_debug'*\n\nHighlight the current line and breakpoints in the debugger.\n\n>\n  let g:go_highlight_debug = 1\n<\n\n                                         *'go:go_debug_breakpoint_sign_text'*\n\nSet the sign text used for breakpoints in the debugger. By default it's '>'.\n\n>\n  let g:go_debug_breakpoint_sign_text = '>'\n<\n\n==============================================================================\nFAQ TROUBLESHOOTING                                     *go-troubleshooting*\n\nHow do I troubleshoot problems?~\n\nOne of the best ways to understand what vim-go is doing and the output from\nthe tools to which it delegates is to leverage the features described in\n|'g:go_debug'|.\n\nCompletion and other functions that use `gopls` don't work~\n\nVim-go is heavily reliant on `gopls` for completion and other functionality.\nMany of the features that use `gopls` (e.g. completion, jumping to\ndefinitions, showing identifier information, et al.) can be configured to\ndelegate to other tools. e.g.  completion via 'omnifunc' and |'g:go_def_mode'|\ncan be set to use other tools for now (though some of the alternatives to\n`gopls` are effectively at their end of life and support for them from within\nvim-go may be removed soon).\n\nI want to disable `gopls`~\n\nVim-go's use of `gopls` can be disabled with 'g:go_gopls_enabled'.\n\nSome users want to do this to limit the load on their system when using vim-go\nconcurrently with an LSP client like vim-lsp. Instead of disabling vim-go's\nuse of `gopls`, you may prefer to configure vim-go to share the `gopls`\ninstance with other LSP plugins. 'g:go_gopls_options' can be used to configure\nhow vim-go starts `gopls` so that the instance can be shared with other\nplugins and vim-go users can leverage the full power of vim-go.\n\nI only want vim-go's syntax highlighting~\n\nUsually when users ask for this, they want to disable vim-go's features that\ntake some action when a buffer is written to disk. The options that control\nthose actions can be found in the vim-go help file. They all contain the\nstring _auto in their names and most are suffixed with _autosave.\n\nI get a \"Unknown function: go#config#...\" error~\n\nThis often happens to vim-polyglot users when new config options are added to\nvim-go. Run vim-polyglot's `build` script or make sure that vim-go is loaded\nbefore vim-polyglot.\n\nIt can also happen when multiple versions of vim-go are installed and the\nversion loaded by Vim doesn't have a function introduced by a later version.\nTo see where vim-go is being loaded from run\n>\n    :verbose function go#config#FmtAutosave\n<\n\nThe output will show the path to the `autoload/go/config.vim` that was loaded\nby Vim. Make sure the root of the path to output by the command is the path\nfrom which vim-go is expected to be sourced. If it is not rooted as expected,\nthen there are multiple copies of vim-go installed; remove the unexpected\ncopies.\n\nI get \"not an editor command\" error when I invoke :GoXXX~\n\nThis happens if vim-go is not installed properly. Be sure you have added this\nline into your vimrc:\n>\n  filetype plugin indent on\n<\n\nI get a \"command not found\" error when I invoke :GoXXX~\n\nIf you try to call |:GoDef|, |:GoInfo| and get a command not found, check that\nyou have the binaries installed by using |:GoInstallBinaries|.\n\nBefore opening vim, check your current $PATH:\n>\n  echo $PATH\n<\nAfter opening vim, run `:echo $PATH`, the output must be your current `$PATH`\nplus `$GOPATH/bin` (the location where |:GoInstallBinaries| installed the\nbinaries).\n\n\n\nVim becomes slow while editing Go files~\n\nThe most common cause for this is using an older version of Vim that doesn't\nsupport asynchronous jobs. |'g:go_auto_sameids'| and |'g:go_auto_type_info'|\nrun jobs that can cause noticeable delays when used with vim74. The problem is\nmost pronounced on vim74, but can occur on vim8 and nvim. On vim8 and nvim,\nthe problem should be restricted to a short period when the first buffer in a\npackage is first loaded.\n\nIf you see unexpected characters rendered in the current window, the problem\nis most likely due to |'g:go_auto_sameids'| or |'g:go_auto_type_info'|. Try\ndisabling |'g:go_auto_sameids'| and |'g:go_auto_type_info'|.\n\nTo a lesser extent, this can be caused by `g:go_highlight_*` options. If Vim\nis just slower than normal, but doesn't render unexpected characters in the\ncurrent window, then the problem is most likely the `g:go_highlight_*`\noptions. Try disabling them if you've enabled some of them.\n\nI get errors when using GoInstallBinaries~\n\nIf you see errors like this:\n>\n  Error installing golang.org/x/tools/cmd/goimports\n<\nthat means your local Go setup is broken or the remote website is down. For\nexample sometimes code.google.com times out. To test, just execute a simple\n`go install`:\n>\n  go install golang.org/x/tools/cmd/goimports@latest\n<\nYou'll see a more detailed error. If this works, vim-go will work too.\n\n\nI want to use a different binary name than \"go\", can I do this?~\n\nThere is no way to directly configure the binary name; but you can use a\nwrapper script; for example if you would like to run `goapp` instead of `go`:\n\n1. In `~/gobin/go` (remember to make it executable):\n>\n     #!/bin/sh\n     # Remove gobin from PATH and run goapp.\n     PATH=${PATH#$HOME/gobin} goapp \"$@\"\n<\n2. Start Vim with `~/gobin` as the first `PATH` entry so it will use the\n   wrapper script:\n>\n     PATH=\"$HOME/gobin/:$PATH\" vim\n<\n   Alternatively you could set `$PATH` in your vimrc with an |:autocmd|.\n\n\nHow do I use vim-go with syntastic?~\n\nSometimes when using both `vim-go` and `syntastic` Vim will start lagging\nwhile saving and opening files. The following fixes this:\n>\n let g:syntastic_go_checkers = ['golint', 'govet']\n let g:syntastic_mode_map = { 'mode': 'active', 'passive_filetypes': ['go'] }\n<\nIf you want to add errcheck you can use golangci-lint as a wrapper:\n>\n let g:syntastic_go_checkers = ['golint', 'govet', 'golangci-lint']\n let g:syntastic_go_gometalinter_args = ['--disable-all', '--enable=errcheck']\n let g:syntastic_mode_map = { 'mode': 'active', 'passive_filetypes': ['go'] }\n<\nAnother issue with `vim-go` and `syntastic` is that the location list window\nthat contains the output of commands such as `:GoBuild` and `:GoTest` might\nnot appear.  To resolve this:\n>\n let g:go_list_type = \"quickfix\"\n<\n\nHow do I run focused ginkgo tests?~\n\nYou must set this environment variable in your `.vimrc`:\n>\n  let $GINKGO_EDITOR_INTEGRATION = \"true\"\n<\n\nUsing with NeoVim~\n\nNote: Neovim currently is not a first class citizen for vim-go. You are free\nto open bug, however I'm not using Neovim so it's hard for me to test it.\nvim-go might not work as well in Neovim as it does in Vim. I'm happy to accept\npull requests or very detailed bug reports. If you're interested to improve\nthe state of Neovim in vim-go you're always welcome!\n\nRun `:GoRun` in a new tab, horizontal split or vertical split terminal\n>\n au FileType go nmap <leader>rt <Plug>(go-run-tab)\n au FileType go nmap <leader>rs <Plug>(go-run-split)\n au FileType go nmap <leader>rv <Plug>(go-run-vertical)\n<\nBy default new terminals are opened in a vertical split. To change it\n>\n let g:go_term_mode = \"split\"\n>\n\nHow can I customize the highlighting?~\n\nAll the highlight groups used by vim-go are prefixed with `go` (e.g.\n`goType`) and are defined in the files in the `syntax` directory. To change\nthe highlighting for any group, add a `highlight` command for the group to\nyour vimrc.  To turn off the highlighting for any group, add `highlight link\ngroup-name NONE` (where `group-name` is the name of the group whose highlight\nyou'd like to turn off) to your vimrc.\n\nSome people may wish to highlight Go's builtins as keywords. To do so, one\nshould simply add `highlight link goBuiltins Keyword` to the `vimrc` file.\n\n==============================================================================\nDEVELOPMENT                                               *go-development*\n\nvim-go supports test files written in VimScript; the way they're run is\nroughly similar to Go tests:\n\n- A `*.vim` file has a corresponding `*_test.vim`.\n- All functions starting with `Test_` are run as test.\n- A test is considered to be \"failed\" if |v:errors| has any entries. You can\n  use one of the |test-functions| to set this, or append to it directly.\n\nA simple example:\n>\n function Test_run_fmt()\n   call assert_equal(expected, actual)\n   ...\n endfunction\n<\nTo run tests vim-go comes with three small helper scripts:\n\n  `scripts/install-vim`   Install a pristine Vim to `/tmp/vim-go-test/`.\n  `scripts/run-vim`       Run a Vim version from `/tmp/vim-go-test/`.\n  `scripts/test`          Run all tests with a Vim from `/tmp/vim-go-test/`.\n\nAll scripts accept a Vim version as the first argument, which can be\n`vim-8.0` or `nvim`. You will need to install a Vim version with\n`install-vim` before you can use `run-vim` or `test`.\n\nYou can install and test all Vim versions by running `make`.\n\n\n==============================================================================\nDONATION                                                         *go-donation*\n\nPeople have asked for this for a long time, now you can be a fully supporter\nby being a patreon at: https://www.patreon.com/bhcleek\n\nBy being a patron, you are enabling vim-go to grow and mature, helping me to\ninvest in bug fixes, new documentation, and improving both current and future\nfeatures. It's completely optional and is just a direct way to support\nvim-go's ongoing development. Thanks!\n\nCheck it out: https://www.patreon.com/bhcleek\n\n\n==============================================================================\nCREDITS                                                         *go-credits*\n\n* Go Authors for official Vim plugins.\n* Gocode, Godef, Golint, Guru, Goimports, Errcheck projects and authors of\n  those projects.\n* Other vim-plugins, thanks for inspiration (vim-golang, go.vim, vim-gocode,\n  vim-godef).\n* vim-go contributors: https://github.com/fatih/vim-go/graphs/contributors.\n\n\n vim: ft=help tw=78 et ts=2 sw=2 sts=2 norl\n"
  },
  {
    "path": "ftdetect/gofiletype.vim",
    "content": "\" vint: -ProhibitAutocmdWithNoGroup\n\n\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\n\" Note: should not use augroup in ftdetect (see :help ftdetect)\nau BufRead,BufNewFile *.go setfiletype go\nau BufRead,BufNewFile *.s setfiletype asm\nau BufRead,BufNewFile *.tmpl set filetype=gohtmltmpl\nau BufRead,BufNewFile go.sum set filetype=gosum\nau BufRead,BufNewFile go.work.sum set filetype=gosum\nau BufRead,BufNewFile go.work set filetype=gowork\n\n\" remove the autocommands for modsim3, and lprolog files so that their\n\" highlight groups, syntax, etc. will not be loaded. *.MOD is included, so\n\" that on case insensitive file systems the module2 autocmds will not be\n\" executed.\nau! BufRead,BufNewFile *.mod,*.MOD\n\" Set the filetype if the first non-comment and non-blank line starts with\n\" 'module <path>'.\nau BufRead,BufNewFile go.mod call s:gomod()\n\nfun! s:gomod()\n  for l:i in range(1, line('$'))\n    let l:l = getline(l:i)\n    if l:l ==# '' || l:l[:1] ==# '//'\n      continue\n    endif\n\n    if l:l =~# '^module .\\+'\n      setfiletype gomod\n    endif\n\n    break\n  endfor\nendfun\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "ftplugin/asm.vim",
    "content": "\" asm.vim: Vim filetype plugin for Go assembler.\n\nif exists(\"b:did_ftplugin\")\n  finish\nendif\nlet b:did_ftplugin = 1\n\n\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nlet b:undo_ftplugin = \"setl fo< com< cms<\n      \\ | exe 'au! vim-go-asm-buffer * <buffer>'\"\n\nsetlocal formatoptions-=t\n\nsetlocal comments=s1:/*,mb:*,ex:*/,://\nsetlocal commentstring=//\\ %s\n\nsetlocal noexpandtab\n\ncommand! -nargs=0 AsmFmt call go#asmfmt#Format()\n\n\" Autocommands\n\" ============================================================================\n\naugroup vim-go-asm-buffer\n  autocmd! * <buffer>\n\n  autocmd BufWritePre <buffer> call go#auto#asmfmt_autosave()\naugroup end\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "ftplugin/go/commands.vim",
    "content": "\" -- gorename\ncommand! -nargs=? -complete=customlist,go#rename#Complete GoRename call go#rename#Rename(<bang>0, <f-args>)\n\ncommand! -range=% GoImplements call go#implements#Implements(<count>)\ncommand! -range=% GoReferrers call go#referrers#Referrers(<count>)\ncommand! -range=0 GoSameIds call go#sameids#SameIds(1)\ncommand! -range=0 GoSameIdsClear call go#sameids#ClearSameIds()\ncommand! -range=0 GoSameIdsToggle call go#sameids#ToggleSameIds()\ncommand! -range=0 GoSameIdsAutoToggle call go#sameids#AutoToggleSameIds()\n\n\" -- calls\ncommand! -nargs=0 GoCallers call go#calls#Callers()\n\n\" -- tags\ncommand! -nargs=* -range GoAddTags call go#tags#Add(<line1>, <line2>, <count>, <f-args>)\ncommand! -nargs=* -range GoRemoveTags call go#tags#Remove(<line1>, <line2>, <count>, <f-args>)\n\n\" -- mod\ncommand! -nargs=0 -range GoModFmt call go#mod#Format()\n\n\" -- tool\ncommand! -nargs=* -complete=customlist,go#tool#ValidFiles GoFiles echo go#tool#Files(<f-args>)\ncommand! -nargs=0 GoDeps echo go#tool#Deps()\ncommand! -nargs=0 GoInfo call go#tool#Info(1)\ncommand! -nargs=0 GoAutoTypeInfoToggle call go#complete#ToggleAutoTypeInfo()\n\n\" -- cmd\ncommand! -nargs=* -bang GoBuild call go#cmd#Build(<bang>0,<f-args>)\ncommand! -nargs=? -bang GoBuildTags call go#cmd#BuildTags(<bang>0, <f-args>)\ncommand! -nargs=* -bang GoGenerate call go#cmd#Generate(<bang>0,<f-args>)\ncommand! -nargs=* -bang -complete=file GoRun call go#cmd#Run(<bang>0,<f-args>)\ncommand! -nargs=* -bang GoInstall call go#cmd#Install(<bang>0, <f-args>)\n\n\" -- test\ncommand! -nargs=* -bang GoTest call go#test#Test(<bang>0, 0, <f-args>)\ncommand! -nargs=* -bang GoTestCompile call go#test#Test(<bang>0, 1, <f-args>)\ncommand! -nargs=* -bang GoTestFile call go#test#File(<bang>0, <f-args>)\ncommand! -nargs=* -bang GoTestFunc call go#test#Func(<bang>0, <f-args>)\n\n\" -- cover\ncommand! -nargs=* -bang GoCoverage call go#coverage#Buffer(<bang>0, <f-args>)\ncommand! -nargs=* -bang GoCoverageClear call go#coverage#Clear()\ncommand! -nargs=* -bang GoCoverageToggle call go#coverage#BufferToggle(<bang>0, <f-args>)\ncommand! -nargs=* -bang GoCoverageBrowser call go#coverage#Browser(<bang>0, <f-args>)\ncommand! -nargs=1 -complete=file GoCoverageOverlay call go#coverage#Overlay(<f-args>)\n\n\" -- play\ncommand! -nargs=0 -range=% GoPlay call go#play#Share(<count>, <line1>, <line2>)\n\n\" -- def\ncommand! -nargs=* -range GoDef :call go#def#Jump('', 0)\ncommand! -nargs=* -range GoDefType :call go#def#Jump('', 1)\ncommand! -nargs=? GoDefPop :call go#def#StackPop(<f-args>)\ncommand! -nargs=? GoDefStack :call go#def#Stack(<f-args>)\ncommand! -nargs=? GoDefStackClear :call go#def#StackClear(<f-args>)\n\n\" -- doc\ncommand! -nargs=* -range -complete=customlist,go#package#Complete GoDoc call go#doc#Open('new', 'split', <f-args>)\ncommand! -nargs=* -range -complete=customlist,go#package#Complete GoDocBrowser call go#doc#OpenBrowser(<f-args>)\n\n\" -- fmt\ncommand! -nargs=0 GoFmt call go#fmt#Format(0)\ncommand! -nargs=0 GoFmtAutoSaveToggle call go#fmt#ToggleFmtAutoSave()\ncommand! -nargs=0 GoImports call go#fmt#Format(1)\n\n\" -- asmfmt\ncommand! -nargs=0 GoAsmFmtAutoSaveToggle call go#asmfmt#ToggleAsmFmtAutoSave()\n\n\" -- import\ncommand! -nargs=? -complete=customlist,go#package#Complete GoDrop call go#import#SwitchImport(0, '', <f-args>, '')\ncommand! -nargs=1 -bang -complete=customlist,go#package#Complete GoImport call go#import#SwitchImport(1, '', <f-args>, '<bang>')\ncommand! -nargs=* -bang -complete=customlist,go#package#Complete GoImportAs call go#import#SwitchImport(1, <f-args>, '<bang>')\n\n\" -- linters\ncommand! -nargs=* -bang GoMetaLinter call go#lint#Gometa(<bang>0, 0, <f-args>)\ncommand! -nargs=0 GoMetaLinterAutoSaveToggle call go#lint#ToggleMetaLinterAutoSave()\ncommand! -nargs=* -bang GoLint call go#lint#Golint(<bang>0, <f-args>)\ncommand! -nargs=* -bang GoVet call go#lint#Vet(<bang>0, <f-args>)\ncommand! -nargs=* -bang -complete=customlist,go#package#Complete GoErrCheck call go#lint#Errcheck(<bang>0, <f-args>)\n\n\" -- alternate\ncommand! -bang GoAlternate call go#alternate#Switch(<bang>0, '')\n\n\" -- decls\ncommand! -nargs=? -complete=file GoDecls call go#decls#Decls(0, <q-args>)\ncommand! -nargs=? -complete=dir GoDeclsDir call go#decls#Decls(1, <q-args>)\n\n\" -- impl\ncommand! -nargs=* -complete=customlist,go#impl#Complete GoImpl call go#impl#Impl(<f-args>)\n\n\" -- template\ncommand! -nargs=0 GoTemplateAutoCreateToggle call go#template#ToggleAutoCreate()\n\n\" -- fillstruct\ncommand! -nargs=0 GoFillStruct call go#fillstruct#FillStruct()\n\n\" -- debug\nif !exists(':GoDebugStart')\n  command! -nargs=* -complete=customlist,go#package#Complete GoDebugStart call go#debug#Start('debug', <f-args>)\n  command! -nargs=* -complete=customlist,go#package#Complete GoDebugTest  call go#debug#Start('test', <f-args>)\n  command! -nargs=* GoDebugTestFunc  call go#debug#TestFunc(<f-args>)\n  command! -nargs=1 GoDebugAttach call go#debug#Start('attach', <f-args>)\n  command! -nargs=? GoDebugConnect call go#debug#Start('connect', <f-args>)\n  command! -nargs=? GoDebugBreakpoint call go#debug#Breakpoint(<f-args>)\nendif\n\n\" -- issue\ncommand! -nargs=0 GoReportGitHubIssue call go#issue#New()\n\n\" -- iferr\ncommand! -nargs=0 GoIfErr call go#iferr#Generate()\n\n\" -- lsp\ncommand! -nargs=+ -complete=dir GoAddWorkspace call go#lsp#AddWorkspaceDirectory(<f-args>)\ncommand! -nargs=0 GoLSPDebugBrowser call go#lsp#DebugBrowser()\ncommand! -nargs=* -bang GoDiagnostics call go#lint#Diagnostics(<bang>0, <f-args>)\ncommand! -nargs=? GoModReload call go#lsp#ModReload()\n\n\" -- term\ncommand! GoToggleTermCloseOnExit call go#term#ToggleCloseOnExit()\n\n\" -- extract\ncommand! -range GoExtract call go#extract#Extract(<line1>, <line2>)\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "ftplugin/go/mappings.vim",
    "content": "\" go_jump_to_error defines whether we should pass the bang attribute to the\n\" command or not. This is only used for mappings, because the user can't pass\n\" the bang attribute to the plug mappings below. So instead of hardcoding it\n\" as 0 (no '!' attribute) or 1 (with '!' attribute) we pass the user setting,\n\" which by default is enabled. For commands the user has the ability to pass\n\" the '!', such as :GoBuild or :GoBuild!\nif !exists(\"g:go_jump_to_error\")\n  let g:go_jump_to_error = 1\nendif\n\n\" Some handy plug mappings\nnnoremap <silent> <Plug>(go-run) :<C-u>call go#cmd#Run(!g:go_jump_to_error)<CR>\n\nif has(\"nvim\") || has(\"terminal\")\n  nnoremap <silent> <Plug>(go-run-vertical) :<C-u>call go#cmd#RunTerm(!g:go_jump_to_error, 'vsplit', [])<CR>\n  nnoremap <silent> <Plug>(go-run-split) :<C-u>call go#cmd#RunTerm(!g:go_jump_to_error, 'split', [])<CR>\n  nnoremap <silent> <Plug>(go-run-tab) :<C-u>call go#cmd#RunTerm(!g:go_jump_to_error, 'tabe', [])<CR>\nendif\n\nnnoremap <silent> <Plug>(go-build) :<C-u>call go#cmd#Build(!g:go_jump_to_error)<CR>\nnnoremap <silent> <Plug>(go-generate) :<C-u>call go#cmd#Generate(!g:go_jump_to_error)<CR>\nnnoremap <silent> <Plug>(go-install) :<C-u>call go#cmd#Install(!g:go_jump_to_error)<CR>\nnnoremap <silent> <Plug>(go-test) :<C-u>call go#test#Test(!g:go_jump_to_error, 0)<CR>\nnnoremap <silent> <Plug>(go-test-func) :<C-u>call go#test#Func(!g:go_jump_to_error)<CR>\nnnoremap <silent> <Plug>(go-test-compile) :<C-u>call go#test#Test(!g:go_jump_to_error, 1)<CR>\nnnoremap <silent> <Plug>(go-test-file) :<C-u>call go#test#File(!g:go_jump_to_error)<CR>\n\nnnoremap <silent> <Plug>(go-coverage) :<C-u>call go#coverage#Buffer(!g:go_jump_to_error)<CR>\nnnoremap <silent> <Plug>(go-coverage-clear) :<C-u>call go#coverage#Clear()<CR>\nnnoremap <silent> <Plug>(go-coverage-toggle) :<C-u>call go#coverage#BufferToggle(!g:go_jump_to_error)<CR>\nnnoremap <silent> <Plug>(go-coverage-browser) :<C-u>call go#coverage#Browser(!g:go_jump_to_error)<CR>\n\nnnoremap <silent> <Plug>(go-files) :<C-u>call go#tool#Files()<CR>\nnnoremap <silent> <Plug>(go-deps) :<C-u>call go#tool#Deps()<CR>\nnnoremap <silent> <Plug>(go-info) :<C-u>call go#tool#Info(1)<CR>\nnnoremap <silent> <Plug>(go-import) :<C-u>call go#import#SwitchImport(1, '', expand('<cword>'), '')<CR>\nnnoremap <silent> <Plug>(go-imports) :<C-u>call go#fmt#Format(1)<CR>\nnnoremap <silent> <Plug>(go-fmt) :<C-u>call go#fmt#Format(0)<CR>\n\nnnoremap <silent> <Plug>(go-implements) :<C-u>call go#implements#Implements(-1)<CR>\nnnoremap <silent> <Plug>(go-callers) :<C-u>call go#calls#Callers()<CR>\nnnoremap <silent> <Plug>(go-referrers) :<C-u>call go#referrers#Referrers(-1)<CR>\nnnoremap <silent> <Plug>(go-sameids) :<C-u>call go#sameids#SameIds(1)<CR>\nnnoremap <silent> <Plug>(go-sameids-toggle) :<C-u>call go#sameids#ToggleSameIds()<CR>\n\nnnoremap <silent> <Plug>(go-rename) :<C-u>call go#rename#Rename(!g:go_jump_to_error)<CR>\n\nnnoremap <silent> <Plug>(go-decls) :<C-u>call go#decls#Decls(0, '')<CR>\nnnoremap <silent> <Plug>(go-decls-dir) :<C-u>call go#decls#Decls(1, '')<CR>\n\nnnoremap <silent> <Plug>(go-def) :<C-u>call go#def#Jump('', 0)<CR>\nnnoremap <silent> <Plug>(go-def-vertical) :<C-u>call go#def#Jump(\"vsplit\", 0)<CR>\nnnoremap <silent> <Plug>(go-def-split) :<C-u>call go#def#Jump(\"split\", 0)<CR>\nnnoremap <silent> <Plug>(go-def-tab) :<C-u>call go#def#Jump(\"tab\", 0)<CR>\n\nnnoremap <silent> <Plug>(go-def-type) :<C-u>call go#def#Jump('', 1)<CR>\nnnoremap <silent> <Plug>(go-def-type-vertical) :<C-u>call go#def#Jump(\"vsplit\", 1)<CR>\nnnoremap <silent> <Plug>(go-def-type-split) :<C-u>call go#def#Jump(\"split\", 1)<CR>\nnnoremap <silent> <Plug>(go-def-type-tab) :<C-u>call go#def#Jump(\"tab\", 1)<CR>\n\nnnoremap <silent> <Plug>(go-def-pop) :<C-u>call go#def#StackPop()<CR>\nnnoremap <silent> <Plug>(go-def-stack) :<C-u>call go#def#Stack()<CR>\nnnoremap <silent> <Plug>(go-def-stack-clear) :<C-u>call go#def#StackClear()<CR>\n\nnnoremap <silent> <Plug>(go-doc) :<C-u>call go#doc#Open(\"new\", \"split\")<CR>\nnnoremap <silent> <Plug>(go-doc-tab) :<C-u>call go#doc#Open(\"tabnew\", \"tabe\")<CR>\nnnoremap <silent> <Plug>(go-doc-vertical) :<C-u>call go#doc#Open(\"vnew\", \"vsplit\")<CR>\nnnoremap <silent> <Plug>(go-doc-split) :<C-u>call go#doc#Open(\"new\", \"split\")<CR>\nnnoremap <silent> <Plug>(go-doc-browser) :<C-u>call go#doc#OpenBrowser()<CR>\n\nnnoremap <silent> <Plug>(go-metalinter) :<C-u>call go#lint#Gometa(!g:go_jump_to_error, 0)<CR>\nnnoremap <silent> <Plug>(go-lint) :<C-u>call go#lint#Golint(!g:go_jump_to_error)<CR>\nnnoremap <silent> <Plug>(go-vet) :<C-u>call go#lint#Vet(!g:go_jump_to_error)<CR>\n\nnnoremap <silent> <Plug>(go-alternate-edit) :<C-u>call go#alternate#Switch(0, \"edit\")<CR>\nnnoremap <silent> <Plug>(go-alternate-vertical) :<C-u>call go#alternate#Switch(0, \"vsplit\")<CR>\nnnoremap <silent> <Plug>(go-alternate-split) :<C-u>call go#alternate#Switch(0, \"split\")<CR>\n\n\" go-iferr is deprecated, but remains for backward compatibility\nnnoremap <silent> <Plug>(go-iferr) :<C-u>call go#iferr#Generate()<CR>\nnnoremap <silent> <Plug>(go-if-err) :<C-u>call go#iferr#Generate()<CR>\n\nnnoremap <silent> <Plug>(go-diagnostics) :<C-u>call go#lint#Diagnostics(!g:go_jump_to_error)<CR>\n\nnnoremap <silent> <Plug>(go-fill-struct) :<C-u>call go#fillstruct#FillStruct()<CR>\n\nxnoremap <silent> <Plug>(go-extract) :<C-u>call go#extract#Extract(0)<CR>\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "ftplugin/go/snippets.vim",
    "content": "\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nif exists(\"g:go_loaded_gosnippets\")\n  finish\nendif\nlet g:go_loaded_gosnippets = 1\n\nfunction! s:GoUltiSnips() abort\n  if get(g:, 'did_plugin_ultisnips') isnot 1\n    return\n  endif\n\n  if !exists(\"g:UltiSnipsSnippetDirectories\")\n    let g:UltiSnipsSnippetDirectories = [\"gosnippets/UltiSnips\"]\n  else\n    let g:UltiSnipsSnippetDirectories += [\"gosnippets/UltiSnips\"]\n  endif\nendfunction\n\nfunction! s:GoNeosnippet() abort\n  if get(g:, 'loaded_neosnippet') isnot 1\n    return\n  endif\n\n  let g:neosnippet#enable_snipmate_compatibility = 1\n\n  let l:gosnippets_dir = globpath(&rtp, 'gosnippets/snippets')\n  if type(g:neosnippet#snippets_directory) == type([])\n    let g:neosnippet#snippets_directory += [l:gosnippets_dir]\n  elseif type(g:neosnippet#snippets_directory) == type(\"\")\n    if strlen(g:neosnippet#snippets_directory) > 0\n      let g:neosnippet#snippets_directory = g:neosnippet#snippets_directory . \",\" . l:gosnippets_dir\n    else\n      let g:neosnippet#snippets_directory = l:gosnippets_dir\n    endif\n  endif\nendfunction\n\nfunction! s:GoMinisnip() abort\n  if get(g:, 'loaded_minisnip') isnot 1\n    return\n  endif\n\n  if exists('g:minisnip_dir')\n    let g:minisnip_dir .= go#util#PathListSep() . globpath(&rtp, 'gosnippets/minisnip')\n  else\n    let g:minisnip_dir = globpath(&rtp, 'gosnippets/minisnip')\n  endif\nendfunction\n\n\nlet s:engine = go#config#SnippetEngine()\nif s:engine is? 'ultisnips'\n  call s:GoUltiSnips()\nelseif s:engine is? 'neosnippet'\n  call s:GoNeosnippet()\nelseif s:engine is? 'minisnip'\n  call s:GoMinisnip()\nendif\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "ftplugin/go/tagbar.vim",
    "content": "\" Check if tagbar is installed under plugins or is directly under rtp\n\" this covers pathogen + Vundle/Bundle\n\"\n\" Also make sure the ctags command exists\n\"\nif !executable('ctags')\n  finish\nelseif globpath(&rtp, 'plugin/tagbar.vim') == \"\"\n  finish\nendif\n\n\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nif !exists(\"g:go_gotags_bin\")\n  let g:go_gotags_bin = \"gotags\"\nendif\n\n\nfunction! s:SetTagbar()\n  let bin_path = go#path#CheckBinPath(g:go_gotags_bin)\n  if empty(bin_path)\n    return\n  endif\n\n  if !exists(\"g:tagbar_type_go\")\n    let g:tagbar_type_go = {\n          \\ 'ctagstype' : 'go',\n          \\ 'kinds'     : [\n          \\ 'p:package',\n          \\ 'i:imports',\n          \\ 'c:constants',\n          \\ 'v:variables',\n          \\ 't:types',\n          \\ 'n:interfaces',\n          \\ 'w:fields',\n          \\ 'e:embedded',\n          \\ 'm:methods',\n          \\ 'r:constructor',\n          \\ 'f:functions'\n          \\ ],\n          \\ 'sro' : '.',\n          \\ 'kind2scope' : {\n          \\ 't' : 'ctype',\n          \\ 'n' : 'ntype'\n          \\ },\n          \\ 'scope2kind' : {\n          \\ 'ctype' : 't',\n          \\ 'ntype' : 'n'\n          \\ },\n          \\ 'ctagsbin'  : bin_path,\n          \\ 'ctagsargs' : '-sort -silent'\n          \\ }\n  endif\nendfunction\n\n\ncall s:SetTagbar()\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "ftplugin/go.vim",
    "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.vim: Vim filetype plugin for Go.\n\nif exists(\"b:did_ftplugin\")\n  finish\nendif\nlet b:did_ftplugin = 1\n\n\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nlet b:undo_ftplugin = \"setl fo< com< cms<\"\n      \\ . \"| exe 'au! vim-go-buffer * <buffer>'\"\n\nsetlocal formatoptions-=t\n\nsetlocal comments=s1:/*,mb:*,ex:*/,://\nsetlocal commentstring=//\\ %s\n\nsetlocal noexpandtab\n\ncompiler go\n\nif go#config#CodeCompletionEnabled()\n  \" Set autocompletion\n  setlocal omnifunc=go#complete#Complete\nendif\n\nif get(g:, \"go_doc_keywordprg_enabled\", 1)\n  \" keywordprg doesn't allow to use vim commands, override it\n  nnoremap <buffer> <silent> K :GoDoc<cr>\nendif\n\nif get(g:, \"go_def_mapping_enabled\", 1)\n  \" these are default Vim mappings, we're overriding them to make them\n  \" useful again for Go source code\n  nnoremap <buffer> <silent> gd :GoDef<cr>\n  nnoremap <buffer> <silent> gD :GoDefType<cr>\n  nnoremap <buffer> <silent> <C-]> :GoDef<cr>\n  nnoremap <buffer> <silent> <C-LeftMouse> <LeftMouse>:GoDef<cr>\n  nnoremap <buffer> <silent> g<LeftMouse> <LeftMouse>:GoDef<cr>\n  nnoremap <buffer> <silent> <C-w><C-]> :<C-u>call go#def#Jump(\"split\", 0)<CR>\n  nnoremap <buffer> <silent> <C-w>] :<C-u>call go#def#Jump(\"split\", 0)<CR>\n  if exists('*settagstack') is 0 || has('patch-8.2.0077') is 0\n    nnoremap <buffer> <silent> <C-t> :<C-U>call go#def#StackPop(v:count1)<cr>\n  endif\nendif\n\nif get(g:, \"go_textobj_enabled\", 1)\n  onoremap <buffer> <silent> af :<c-u>call go#textobj#Function('a')<cr>\n  xnoremap <buffer> <silent> af :<c-u>call go#textobj#Function('a')<cr>\n\n  onoremap <buffer> <silent> if :<c-u>call go#textobj#Function('i')<cr>\n  xnoremap <buffer> <silent> if :<c-u>call go#textobj#Function('i')<cr>\n\n  onoremap <buffer> <silent> ac :<c-u>call go#textobj#Comment('a')<cr>\n  xnoremap <buffer> <silent> ac :<c-u>call go#textobj#Comment('a')<cr>\n\n  onoremap <buffer> <silent> ic :<c-u>call go#textobj#Comment('i')<cr>\n  xnoremap <buffer> <silent> ic :<c-u>call go#textobj#Comment('i')<cr>\n\n  \" Remap ]] and [[ to jump betweeen functions as they are useless in Go\n  nnoremap <buffer> <silent> ]] :<c-u>call go#textobj#FunctionJump('n', 'next')<cr>\n  nnoremap <buffer> <silent> [[ :<c-u>call go#textobj#FunctionJump('n', 'prev')<cr>\n\n  onoremap <buffer> <silent> ]] :<c-u>call go#textobj#FunctionJump('o', 'next')<cr>\n  onoremap <buffer> <silent> [[ :<c-u>call go#textobj#FunctionJump('o', 'prev')<cr>\n\n  xnoremap <buffer> <silent> ]] :<c-u>call go#textobj#FunctionJump('v', 'next')<cr>\n  xnoremap <buffer> <silent> [[ :<c-u>call go#textobj#FunctionJump('v', 'prev')<cr>\nendif\n\n\" Autocommands\n\" ============================================================================\n\"\naugroup vim-go-buffer\n  autocmd! * <buffer>\n\n  \" The file is registered (textDocument/DidOpen) with gopls in plugin/go.vim\n  \" on the FileType event.\n\n  if go#util#has_job()\n    autocmd BufWritePost,FileChangedShellPost <buffer> call go#lsp#DidChange(resolve(expand('<afile>:p')))\n    autocmd BufDelete <buffer> call go#lsp#DidClose(resolve(expand('<afile>:p')))\n  endif\n\n  \" send the textDocument/didChange notification when idle. go#lsp#DidChange\n  \" will not send an event if the buffer hasn't changed since the last\n  \" notification.\n  autocmd CursorHold,CursorHoldI <buffer> call go#lsp#DidChange(resolve(expand('<afile>:p')))\n\n  autocmd BufEnter,CursorHold <buffer> call go#auto#update_autocmd()\n\n  \" Echo the identifier information when completion is done. Useful to see\n  \" the signature of a function, etc...\n  if exists('##CompleteDone')\n    autocmd CompleteDone <buffer> call go#auto#complete_done()\n  endif\n\n  autocmd BufWritePre <buffer> call go#auto#fmt_autosave()\n  autocmd BufWritePost <buffer> call go#auto#metalinter_autosave()\n\n  \" TODO(bc): autocmd BufWinLeave call go#lsp#DidChange(expand('<afile>:p'))\n\n  if !has('textprop')\n    \"TODO(bc): how to clear sameids and diagnostics when a non-go buffer is\n    \" loaded into a window and the previously loaded buffer is still loaded in\n    \" another window?\n\n    \" TODO(bc): only clear when the new buffer isn't the old buffer\n\n    \" clear SameIds when the buffer is unloaded from its last window so that\n    \" loading another buffer (especially of a different filetype) in the same\n    \" window doesn't highlight the most recently matched identifier's positions.\n    autocmd BufWinLeave <buffer> call go#sameids#ClearSameIds()\n    \" clear SameIds when a new buffer is loaded in the window so that the\n    \" previous buffer's highlighting isn't used.\n    autocmd BufWinEnter <buffer> call go#sameids#ClearSameIds()\n\n    \" clear diagnostics when the buffer is unloaded from its last window so that\n    \" loading another buffer (especially of a different filetype) in the same\n    \" window doesn't highlight the previously loaded buffer's diagnostics.\n    autocmd BufWinLeave <buffer> call go#lsp#ClearDiagnosticHighlights()\n    \" clear diagnostics when a new buffer is loaded in the window so that the\n    \" previous buffer's diagnostics aren't used.\n    \"autocmd BufWinEnter <buffer> call go#lsp#ClearDiagnosticHighlights()\n  endif\naugroup end\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "ftplugin/godoc/commands.vim",
    "content": "\" -- doc\ncommand! -nargs=* -range -complete=customlist,go#package#Complete GoDoc call go#doc#Open('new', 'split', <f-args>)\ncommand! -nargs=* -range -complete=customlist,go#package#Complete GoDocBrowser call go#doc#OpenBrowser(<f-args>)\n"
  },
  {
    "path": "ftplugin/godoc/mappings.vim",
    "content": "nnoremap <silent> <Plug>(go-doc) :<C-u>call go#doc#Open(\"new\", \"split\")<CR>\nnnoremap <silent> <Plug>(go-doc-tab) :<C-u>call go#doc#Open(\"tabnew\", \"tabe\")<CR>\nnnoremap <silent> <Plug>(go-doc-vertical) :<C-u>call go#doc#Open(\"vnew\", \"vsplit\")<CR>\nnnoremap <silent> <Plug>(go-doc-split) :<C-u>call go#doc#Open(\"new\", \"split\")<CR>\nnnoremap <silent> <Plug>(go-doc-browser) :<C-u>call go#doc#OpenBrowser()<CR>\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "ftplugin/godoc.vim",
    "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.vim: Vim filetype plugin for Go.\n\nif exists(\"b:did_ftplugin\")\n  finish\nendif\nlet b:did_ftplugin = 1\n\n\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nif get(g:, \"go_doc_keywordprg_enabled\", 1)\n  \" keywordprg doesn't allow to use vim commands, override it\n  nnoremap <buffer> <silent> K :GoDoc<cr>\nendif\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "ftplugin/gohtmltmpl.vim",
    "content": "if exists(\"b:did_ftplugin\")\n  finish\nendif\n\nruntime! ftplugin/html.vim\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "ftplugin/gomod/commands.vim",
    "content": "command! -nargs=0 -range GoModFmt call go#mod#Format()\n\ncommand! -nargs=0 GoModFmtAutoSaveToggle call go#mod#ToggleModFmtAutoSave()\n"
  },
  {
    "path": "ftplugin/gomod/mappings.vim",
    "content": "nnoremap <silent> <Plug>(go-mod-fmt) :<C-u>call go#mod#Format()<CR>\n"
  },
  {
    "path": "ftplugin/gomod.vim",
    "content": "\" gomod.vim: Vim filetype plugin for Go assembler.\n\nif exists(\"b:did_ftplugin\")\n  finish\nendif\nlet b:did_ftplugin = 1\n\n\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nlet b:undo_ftplugin = \"setl fo< com< cms<\n      \\ | exe 'au! vim-go-gomod-buffer * <buffer>'\"\n\nsetlocal formatoptions-=t\n\nsetlocal comments=://\nsetlocal commentstring=//\\ %s\n\n\" Autocommands\n\" ============================================================================\n\naugroup vim-go-gomod-buffer\n  autocmd! * <buffer>\n\n  autocmd BufWritePre <buffer> call go#auto#modfmt_autosave()\n  if go#util#has_job()\n    autocmd BufWritePost,FileChangedShellPost <buffer> call go#lsp#ModReload(resolve(expand('<afile>:p')))\n  endif\naugroup end\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "gosnippets/UltiSnips/go.snippets",
    "content": "# Snippets for Go\n\npriority -10\n\n# shorthand variable declaration\nsnippet : \"v := value\"\n${1} := ${0}\nendsnippet\n\n# anonymous function\nsnippet anon \"fn := func() { ... }\"\n${1:fn} := func() {\n\t${2:${VISUAL}}\n}\n${0}\nendsnippet\n\n# append\nsnippet ap \"append(slice, value)\"\nappend(${1:slice}, ${0:value})\nendsnippet\n\n# append assignment\nsnippet ap= \"a = append(a, value)\"\n${1:slice} = append($1, ${0:value})\nendsnippet\n\n# break\nsnippet br \"break\"\nbreak\nendsnippet\n\n# channel\nsnippet ch \"chan Type\"\nchan ${0:int}\nendsnippet\n\n# case\nsnippet case \"case ...:\"\ncase ${1:value}:\n\t${0:${VISUAL}}\nendsnippet\n\n# constant\nsnippet con \"const XXX Type = ...\"\nconst ${1:NAME} ${2:Type} = ${0:0}\nendsnippet\n\n# constants\nsnippet cons \"const ( ... )\"\nconst (\n\t${1:NAME} ${2:Type} = ${3:value}\n\t${0}\n)\nendsnippet\n\n# constants with iota\nsnippet iota \"const ( ... = iota )\"\nconst (\n\t${1:NAME} ${2:Type} = iota\n\t${0}\n)\nendsnippet\n\n# continue\nsnippet cn \"continue\"\ncontinue\nendsnippet\n\n# default case\nsnippet default \"default: ...\"\ndefault:\n\t${0:${VISUAL}}\nendsnippet\n\n# defer\nsnippet df \"defer someFunction()\"\ndefer ${1:func}(${2})\n${0}\nendsnippet\n\nsnippet def \"defer func() { ... }\"\ndefer func() {\n\t${0:${VISUAL}}\n}()\nendsnippet\n\n# defer recover\nsnippet defr\ndefer func() {\n\tif err := recover(); err != nil {\n\t\t${0:${VISUAL}}\n\t}\n}()\nendsnippet\n\n# gpl\nsnippet gpl\n/*\n* This program is free software; you can redistribute it and/or modify\n* it under the terms of the GNU General Public License as published by\n* the Free Software Foundation; either version 2 of the License, or\n* (at your option) any later version.\n*\n* This program is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n* GNU General Public License for more details.\n*\n* You should have received a copy of the GNU General Public License\n* along with this program; if not, see <http://www.gnu.org/licenses/>.\n*\n* Copyright (C) ${1:Author}, `!v strftime(\"%Y\")`\n*/\n${0}\nendsnippet\n\n# import\nsnippet import \"import ( ... )\"\nimport (\n\t\"${1:package}\"\n)\nendsnippet\n\n# full interface snippet\nsnippet interface \"interface I { ... }\"\ntype ${1:Interface} interface {\n\t${2:/* TODO: add methods */}\n}\nendsnippet\n\n# if condition\nsnippet if \"if ... { ... }\"\nif ${1:condition} {\n\t${0:${VISUAL}}\n}\nendsnippet\n\n# else snippet\nsnippet else\nelse {\n\t${0:${VISUAL}}\n}\nendsnippet\n\n# if inline error\nsnippet ife \"If with inline error\"\nif err := ${1:condition}; err != nil {\n\t${0:${VISUAL}}\n}\nendsnippet\n\nsnippet ew \"errors.Wrap\"\nerrors.Wrap(${1:err}, \"${2:message}\")\nendsnippet\n\nsnippet ewf \"errors.Wrapf\"\nerrors.Wrapf(${1:err}, \"${2:message %v}\", ${3:args...})\nendsnippet\n\n# error snippet\nsnippet errn \"Error return\" !b\nif err != nil {\n\treturn err\n}\n${0}\nendsnippet\n\nsnippet errnw \"Error return wrap\" !b\nif err != nil {\n\treturn errors.Wrap(err, \"${1:message}\")\n}\n${0}\nendsnippet\n\nsnippet errnwf \"Error return wrapf\" !b\nif err != nil {\n\treturn errors.Wrapf(err, \"${1:message %v}\", ${2:args...})\n}\n${0}\nendsnippet\n\n# error log snippet\nsnippet errl \"Error with log.Fatal(err)\" !b\nif err != nil {\n\tlog.Fatal(err)\n}\n${0}\nendsnippet\n\n# error multiple return\nsnippet errn, \"Error return with two return values\" !b\nif err != nil {\n\treturn ${1:nil}, ${2:err}\n}\n${0}\nendsnippet\n\nsnippet errn,w \"Error return wrap with two return values\" !b\nif err != nil {\n\treturn nil, errors.Wrap(err, \"${1:message}\")\n}\n${0}\nendsnippet\n\nsnippet errn,wf \"Error return wrapf with two return values\" !b\nif err != nil {\n\treturn nil, errors.Wrapf(err, \"${1:message %v}\", ${2:args...})\n}\n${0}\nendsnippet\n\n# error panic\nsnippet errp \"Error panic\" !b\nif err != nil {\n\tpanic(${1})\n}\n${0}\nendsnippet\n\n# error test\nsnippet errt \"Error test fatal \" !b\nif err != nil {\n\tt.Fatal(err)\n}\n${0}\nendsnippet\n\n# error handle\nsnippet errh \"Error handle and return\" !b\nif err != nil {\n\t${1}\n\treturn\n}\n${0}\nendsnippet\n\n# json field tag\nsnippet json \"\\`json:key\\`\"\n\\`json:\"${1:`!v  go#util#snippetcase(matchstr(getline(\".\"), '\\w\\+'))`}\"\\`\nendsnippet\n\n# yaml field tag\nsnippet yaml \"\\`yaml:key\\`\"\n\\`yaml:\"${1:`!v  go#util#snippetcase(matchstr(getline(\".\"), '\\w\\+'))`}\"\\`\nendsnippet\n\n# fallthrough\nsnippet ft \"fallthrough\"\nfallthrough\nendsnippet\n\n# for loop\nsnippet for \"for ... { ... }\"\nfor ${1} {\n\t${0:${VISUAL}}\n}\nendsnippet\n\n# for integer loop\nsnippet fori \"for 0..N-1 { ... }\"\nfor ${1:i} := 0; $1 < ${2:N}; $1++ {\n\t${0:${VISUAL}}\n}\nendsnippet\n\n# for range loop\nsnippet forr \"for k, v := range items { ... }\"\nfor ${2:k}, ${3:v} := range ${1} {\n\t${0:${VISUAL}}\n}\nendsnippet\n\nsnippet forsel \"for select\"\nfor {\n\tselect {\n\t\tcase ${2:${1:result} := }<- ${3:channel}:\n\t\t\t${0}\n\t}\n}\nendsnippet\n\nsnippet selc \"select case\" !b\ncase ${1:${2:var} := }<-${3:channel}:\n  ${0}\nendsnippet\n\n# function\nsnippet func \"func Function(...) [error] { ... }\"\nfunc ${1:name}(${2:params})${3/(.+)/ /}`!p opening_par(snip, 3)`$3`!p closing_par(snip, 3)` {\n\t${0:${VISUAL}}\n}\nendsnippet\n\n# Fmt Printf debug\nsnippet ff \"fmt.Printf(...)\"\nfmt.Printf(\"$1 = %+v\\n\", ${1:${VISUAL}})\nendsnippet\n\n# Fmt Printf debug with hash\nsnippet ffh \"fmt.Printf(#...) hash\"\nfmt.Printf(\"$1 = %#v\\n\", ${1:${VISUAL}})\nendsnippet\n\n# Fmt Println debug\nsnippet fn \"fmt.Println(...)\"\nfmt.Println(\"${1:${VISUAL}}\")\nendsnippet\n\n# Fmt Errorf debug\nsnippet fe \"fmt.Errorf(...)\"\nfmt.Errorf(\"${1:${VISUAL}}\")\nendsnippet\n\n# Fmt Errorf wrap\nsnippet few \"fmt.Errorf(%w, err)\"\nfmt.Errorf(\"${1:message}: %w\", ${2:${VISUAL:err}})\nendsnippet\n\n# Fmt Errorf wrap and return\nsnippet errnfw \"Error return fmt.Errorf(%w, err)\" !b\nif ${1:${VISUAL:err}} != nil {\n\treturn fmt.Errorf(\"${2:message}: %w\", $1)\n}\nendsnippet\n\n# log printf\nsnippet lf \"log.Printf(...)\"\nlog.Printf(\"${1:${VISUAL}} = %+v\\n\", $1)\nendsnippet\n\n# log println\nsnippet ln \"log.Println(...)\"\nlog.Println(\"${1:${VISUAL}}\")\nendsnippet\n\n# make\nsnippet make \"make(Type, size)\"\nmake(${1:[]string}, ${2:0})${0}\nendsnippet\n\n# map\nsnippet map \"map[Type]Type\"\nmap[${1:string}]${0:int}\nendsnippet\n\n# main()\nsnippet main \"func main() { ... }\"\nfunc main() {\n\t${0:${VISUAL}}\n}\nendsnippet\n\n# method\nsnippet meth \"func (self Type) Method(...) [error] { ... }\"\nfunc (${1:receiver} ${2:type}) ${3:name}(${4:params})${5/(.+)/ /}`!p opening_par(snip, 5)`$5`!p closing_par(snip, 5)` {\n\t${0:${VISUAL}}\n}\nendsnippet\n\n# ok\nsnippet ok \"if !ok { ... }\"\nif !ok {\n\t${0:${VISUAL}}\n}\nendsnippet\n\n# package\nsnippet package \"package ...\"\n// Package $1 provides ${2:...}\npackage ${1:main}\n${0}\nendsnippet\n\n# panic\nsnippet pn \"panic()\"\npanic(\"${0:msg}\")\nendsnippet\n\n# return\nsnippet rt \"return\"\nreturn ${0:${VISUAL}}\nendsnippet\n\n# select\nsnippet select \"select { case a := <-chan: ... }\"\nselect {\ncase ${1:v1} := <-${2:chan1}:\n\t${0}\n}\nendsnippet\n\n# struct\nsnippet st \"type T struct { ... }\"\ntype ${1:Type} struct {\n\t${0}\n}\nendsnippet\n\n# switch\nsnippet switch \"switch x { ... }\"\nswitch ${1:var} {\ncase ${2:value1}:\n\t${0}\n}\nendsnippet\n\nsnippet tswitch \"type switch x { ... }\"\nswitch ${2:$1 := }${1:v}.(type) {\n\t${0}\n}\nendsnippet\n\n# sprintf\nsnippet sp \"fmt.Sprintf(...)\"\nfmt.Sprintf(\"%${1:s}\", ${2:var})\nendsnippet\n\n# goroutine named function\nsnippet go \"go someFunc(...)\"\ngo ${1:funcName}(${0})\nendsnippet\n\n# goroutine anonymous function\nsnippet gof \"go func() { ... }()\"\ngo func() {\n\t${1:${VISUAL}}\n}()\n${0}\nendsnippet\n\n# test function\nsnippet test \"func TestXYZ(t *testing.T) { ... }\"\nfunc Test${1:Function}(t *testing.T) {\n\t${0:${VISUAL}}\n}\nendsnippet\n\n# test t.Run\nsnippet tr \"t.Run(XYZ, func(t *testing.T){ ... })\"\nt.Run(\"${0}\", func(t *testing.T){\n\n})\nendsnippet\n\n# test table snippet\nsnippet tt\nvar tests = []struct {\n\tname string\n\texpected string\n\tgiven string\n}{\n\t{\"${1}\", \"${2}\", \"${3}\",},\n}\nfor _, tt := range tests {\n\ttt := tt\n\tt.Run(tt.name, func(t *testing.T){\n\t\tactual := ${0:${VISUAL}}(tt.given)\n\t\tif actual != tt.expected {\n\t\t\t\tt.Errorf(\"$0(%s): expected %s, actual %s\", tt.given, tt.expected, actual)\n\t\t}\n\n\t})\n}\nendsnippet\n\n# fuzz function\nsnippet fuzz \"func FuzzXYZ(f *testing.F) { ... }\"\nfunc Fuzz${1:Function}(f *testing.F) {\n\tf.Fuzz(func(t *testing.T, ${2}) {\n\t\t${0:${VISUAL}}\n\t})\n}\nendsnippet\n\nsnippet hf \"http.HandlerFunc\"\nfunc ${1:handler}(w http.ResponseWriter, r *http.Request) {\n\t${0:fmt.Fprintf(w, \"hello world\")}\n}\nendsnippet\n\nsnippet hhf \"mux.HandleFunc\" !b\n${1:http}.HandleFunc(\"${2:/}\", func(w http.ResponseWriter, r *http.Request) {\n\t${0:fmt.Fprintf(w, \"hello world\")}\n})\nendsnippet\n\n# quick test server\nsnippet tsrv \"httptest.NewServer\"\nts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\tfmt.Fprintln(w, ${1:`response`})\n}))\ndefer ts.Close()\n\n${0:someUrl} = ts.URL\nendsnippet\n\n# test error handling\nsnippet ter \"if err != nil { t.Errorf(...) }\"\nif err != nil {\n\tt.Errorf(\"${0:message}\")\n}\nendsnippet\n\n# test fatal error\nsnippet terf \"if err != nil { t.Fatalf(...) }\"\nif err != nil {\n\tt.Fatalf(\"${0:message}\")\n}\nendsnippet\n\nsnippet example \"func ExampleXYZ() { ... }\"\nfunc Example${1:Method}() {\n\t${0:${VISUAL}}\n\t// Output:\n}\nendsnippet\n\nsnippet benchmark \"func BenchmarkXYZ(b *testing.B) { ... }\"\nfunc Benchmark${1:Method}(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t${0:${VISUAL}}\n\t}\n}\nendsnippet\n\n# variable declaration\nsnippet var \"var x Type [= ...]\"\nvar ${1:x} ${2:Type}${3: = ${0:value}}\nendsnippet\n\n# variables declaration\nsnippet vars \"var ( ... )\"\nvar (\n\t${1:x} ${2:Type}${3: = ${0:value}}\n)\nendsnippet\n\n# equals fails the test if exp is not equal to act.\nsnippet eq \"equals: test two identifiers with DeepEqual\"\nif !reflect.DeepEqual(${1:expected}, ${2:actual}) {\n\t_, file, line, _ := runtime.Caller(0)\n\tfmt.Printf(\"%s:%d:\\n\\n\\texp: %#v\\n\\n\\tgot: %#v\\n\\n\", filepath.Base(file), line, $1, $2)\n\tt.FailNow()\n}\nendsnippet\n\nglobal !p\n\nimport re\n\n# Automatically wrap return types with parentheses\n\ndef return_values(s):\n\t# remove everything wrapped in parentheses\n\ts = re.sub(r\"\\(.*?\\)|\\([^)]*$\", \"\", s)\n\treturn len(s.split(\",\"))\n\ndef opening_par(snip, pos):\n\tif return_values(t[pos]) > 1 and not t[pos].startswith(\"(\"):\n\t\tsnip.rv = \"(\"\n\telse:\n\t\tsnip.rv = \"\"\n\ndef closing_par(snip, pos):\n\tif return_values(t[pos]) > 1:\n\t\tsnip.rv = \")\"\n\telse:\n\t\tsnip.rv = \"\"\n\nendglobal\n\n# vim:ft=snippets:\n"
  },
  {
    "path": "gosnippets/minisnip/_go_eq",
    "content": "if !reflect.DeepEqual({{+got+}}, {{+want+}}) {\n\tt.Errorf(\"\\ngot:  %#v\\nwant: %#v\\n\", {{+~\\~2+}}, {{+~\\~2+}})\t\n}\n"
  },
  {
    "path": "gosnippets/minisnip/_go_err",
    "content": "if err != nil {\n\treturn {{+err+}}\n}\n"
  },
  {
    "path": "gosnippets/minisnip/_go_errt",
    "content": "if err != nil {\n\tt.Fatal(err)\n}\n{{++}}\n"
  },
  {
    "path": "gosnippets/minisnip/_go_errw",
    "content": "if err != nil {\n\treturn errors.Wrap(err, \"{{++}}\")\n}\n"
  },
  {
    "path": "gosnippets/minisnip/_go_f",
    "content": "// {{++}}\nfunc {{+~\\~1+}}() {\n}\n"
  },
  {
    "path": "gosnippets/minisnip/_go_ff",
    "content": "fmt.Printf(\"%#v\\n\", {{++}})\n"
  },
  {
    "path": "gosnippets/minisnip/_go_fori",
    "content": "for i := 0; i < {{++}}; i++ {\n\t{{++}}\n}\n"
  },
  {
    "path": "gosnippets/minisnip/_go_pkg",
    "content": "// Package {{+~expand('%:p:h:t')+}} {{++}}\npackage {{+~\\~2+}}\n"
  },
  {
    "path": "gosnippets/minisnip/_go_sp",
    "content": "fmt.Sprintf(\"{{++}}\", {{++}})\n\n"
  },
  {
    "path": "gosnippets/minisnip/_go_tt",
    "content": "var tests = []struct {\n\tname string\n\texpected string\n\tgiven string\n}{\n\t{\"\", \"\", \"\",},\n}\nfor _, tt := range tests {\n\ttt := tt\n\tt.Run(tt.name, func(t *testing.T){\n\t\tactual := {{++}}(tt.given)\n\t\tif actual != tt.expected {\n\t\t\t\tt.Errorf(\"{{+~\\~1+}}(%s): expected %s, actual %s\", tt.given, tt.expected, actual)\n\t\t}\n\n\t})\n}\n"
  },
  {
    "path": "gosnippets/snippets/go.snip",
    "content": "# shorthand variable declaration\nsnippet :\nabbr v := value\n\t${1} := ${0}\n# anonymous function\nsnippet anon\nabbr fn := func() { ... }\n\t${1:fn} := func() {\n\t\t${0}\n\t}\n# append\nsnippet ap\nabbr append(slice, value)\n\tappend(${1:slice}, ${0:value})\n# append assign\nsnippet ap=\nabbr slice = append(slice, value)\n  ${1:slice} = append($1, ${0:value})\n# break\nsnippet br\nabbr break\n\tbreak\n# channel\nsnippet ch\nabbr chan Type\n\tchan ${0:int}\n# case\nsnippet case\nabbr case ...:\n\tcase ${1:value}:\n\t\t${0}\n# constant\nsnippet con\nabbr const XXX Type = ...\n\tconst ${1:NAME} ${2:Type} = ${0:0}\n# constants\nsnippet cons\nabbr const ( ... )\n\tconst (\n\t\t${1:NAME} ${2:Type} = ${3:value}\n\t\t${0}\n\t)\n# constants with iota\nsnippet iota\nabbr const ( ... = iota )\n\tconst (\n\t\t${1:NAME} ${2:Type} = iota\n\t\t${0}\n\t)\n# continue\nsnippet cn\nabbr continue\n\tcontinue\n# default case\nsnippet default\nabbr default: ...\n\tdefault:\n\t\t${0}\n\n# defer\nsnippet df\nabbr defer someFunction()\n\tdefer ${1:func}(${2})\n\t${0}\nsnippet def\nabbr defer func() { ... }\n\tdefer func() {\n\t\t${0}\n\t}()\n# defer recover\nsnippet defr\n\tdefer func() {\n\t\tif err := recover(); err != nil {\n\t\t\t${0}\n\t\t}\n\t}()\n# gpl\nsnippet gpl\n\t/*\n\t * This program is free software; you can redistribute it and/or modify\n\t * it under the terms of the GNU General Public License as published by\n\t * the Free Software Foundation; either version 2 of the License, or\n\t * (at your option) any later version.\n\t *\n\t * This program is distributed in the hope that it will be useful,\n\t * but WITHOUT ANY WARRANTY; without even the implied warranty of\n\t * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\t * GNU General Public License for more details.\n\t *\n\t * You should have received a copy of the GNU General Public License\n\t * along with this program; if not, see <http://www.gnu.org/licenses/>.\n\t *\n\t * Copyright (C) ${1:Author}, `strftime(\"%Y\")`\n\t */\n\n\t${0}\n# import\nsnippet import\nabbr import ( ... )\n\timport (\n\t\t\"${1:package}\"\n\t)\n# full interface snippet\nsnippet interface\nabbr interface I { ... }\n\ttype ${1:Interface} interface {\n\t\t${2:/* TODO: add methods */}\n\t}\n# if condition\nsnippet if\nabbr if ... { ... }\n\tif ${1:condition} {\n\t\t${0}\n\t}\n# else snippet\nabbr else { ... }\nsnippet else\n\telse {\n\t\t${0}\n\t}\n\n# if inline error\nsnippet ife\nabbr if err := ...; err != nil { ... }\n\tif err := ${1:condition}; err != nil {\n\t\t${0}\n\t}\n\n# error snippet\nsnippet errn\nabbr if err != nil { return err }\n\tif err != nil {\n\t\treturn err\n\t}\n\t${0}\n# error snippet in TestFunc\nsnippet errt\nabbr if err != nil { t.Fatal(err) }\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n# error snippet in log.Fatal\nsnippet errl\nabbr if err != nil { log.Fatal(err) }\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n# error snippet with two return values\nsnippet errn,\nabbr if err != nil { return [...], err }\n\tif err != nil {\n\t\treturn ${1:nil}, err\n\t}\n\t${0}\n\n# error snippet handle and return\nsnippet errh\nabbr if err != nil { ... return }\n\tif err != nil {\n\t\t${1}\n\t\treturn\n\t}\n\t${0}\n\n# error snippet with panic\nsnippet errp\nabbr if err != nil { panic(...) }\n\tif err != nil {\n\t\tpanic(${1})\n\t}\n\t${0}\n\n# json snippet\nsnippet json\nabbr \\`json:key\\`\n\t\\`json:\"${1:keyName}\"\\`\n\n# yaml snippet\nsnippet yaml\nabbr \\`yaml:key\\`\n\t\\`yaml:\"${1:keyName}\"\\`\n\n# fallthrough\nsnippet ft\nabbr fallthrough\n\tfallthrough\n# for loop\nsnippet for\nabbr for ... { ... }\n\tfor ${1} {\n\t\t${0}\n\t}\n# for integer loop\nsnippet fori\nabbr for 0..N-1 { ... }\n\tfor ${1:i} := 0; $1 < ${2:N}; $1++ {\n\t\t${0}\n\t}\n# for range loop\nsnippet forr\nabbr for k, v := range items { ... }\n\tfor ${2:k}, ${3:v} := range ${1} {\n\t\t${0}\n\t}\n# function\nsnippet func\nabbr func function(...) [error] { ... }\n\tfunc ${1:function}(${2}) ${3:error }{\n\t\t${0}\n\t}\n# Fmt Printf debug\nsnippet ff\nabbr fmt.Printf(...)\n\tfmt.Printf(\"${1} = %+v\\n\", $1)\n\t${0}\n# Fmt Println debug\nsnippet fn\nabbr fmt.Println(...)\n\tfmt.Println(\"${1}\")\n# Fmt Errorf\nsnippet fe\nabbr fmt.Errorf(...)\n\tfmt.Errorf(\"${1}\")\n# log printf\nsnippet lf\nabbr log.Printf(...)\n\tlog.Printf(\"${1} = %+v\\n\", $1)\n# log println\nsnippet ln\nabbr log.Println(...)\n\tlog.Println(\"${1}\")\n# make\nsnippet make\nabbr make(Type, size)\n\tmake(${1:[]string}, ${2:0})${0}\n# map\nsnippet map\nabbr map[Type]Type\n\tmap[${1:string}]${0:int}\n# main()\nsnippet main\nabbr func main() { ... }\noptions head\n\tfunc main() {\n\t\t${0}\n\t}\n# method\nsnippet meth\nabbr func (self Type) Method(...) [error] { ... }\nregexp /^meth/\n\tfunc (${1:self} ${2:Type}) ${3:Do}(${4}) ${5:error }{\n\t\t${0}\n\t}\n# ok\nsnippet ok\nabbr if !ok { ... }\n\tif !ok {\n\t\t${0}\n\t}\n# package\nsnippet package\nabbr package ...\n\t// Package $1 provides ${2:...}\n\tpackage ${1:main}\n\t${0}\n# panic\nsnippet panic\nalias pn\nabbr panic(\"...\")\n\tpanic(\"${0}\")\n# return\nsnippet return\nalias rt\nabbr return ...\n\treturn ${0}\n# select\nsnippet select\nabbr select { case a := <-chan: ... }\n\tselect {\n\tcase ${1:v1} := <-${2:chan1}\n\t\t${0}\n\t}\n# struct\nsnippet st\nabbr type T struct { ... }\n\ttype ${1:Type} struct {\n\t\t${0}\n\t}\n# switch\nsnippet switch\nabbr switch x { ... }\n\tswitch ${1:var} {\n\tcase ${2:value1}:\n\t\t${0}\n\t}\n# sprintf\nsnippet sp\nabbr fmt.Sprintf(...)\n\tfmt.Sprintf(\"%${1:s}\", ${2:var})\n# goroutine named function\nsnippet go\nabbr go someFunc(...)\n\tgo ${1:funcName}(${0})\n# goroutine anonymous function\nsnippet gof\nabbr go func(...) { ... }(...)\n\tgo func(${1}) {\n\t\t${3:/* TODO */}\n\t}(${2})\n# test function\nsnippet test\nabbr func TestXYZ(t *testing.T) { ... }\n\tfunc Test${1:Function}(t *testing.T) {\n\t\t${0}\n\t}\n# test t.Run\nsnippet tr\nabbr t.Run(\"test name\", func(t *testing.T){ ... })\n  t.Run(\"${0}\", func(t *testing.T){\n\n  })\n# test table snippet\nsnippet tt\nabbr var test = {...}{...} for {t.Run(){...}}\n    var tests = []struct {\n        name string\n        expected string\n        given string\n    }{\n        {\"${2}\", \"${3}\", \"${4}\",},\n    }\n    for _, tt := range tests {\n        tt := tt\n        t.Run(tt.name, func(t *testing.T){\n            actual := ${1:Function}(tt.given)\n            if actual != tt.expected {\n                t.Errorf(\"given(%s): expected %s, actual %s\", tt.given, tt.expected, actual)\n            }\n        })\n    }\n# fuzz function\nsnippet fuzz\nabbr func FuzzXYZ(f *testing.F) { ... }\n\tfunc Fuzz${1:Function}(f *testing.F) {\n        f.Fuzz(func(t *testing.T, ${2:ff}) {\n            ${0}\n        })\n\t}\n# test server\nsnippet tsrv\nabbr ts := httptest.NewServer(...)\n  ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n    fmt.Fprintln(w, ${1:`response`})\n  }))\n  defer ts.Close()\n\n  //Use testing server url (type string) somewhere\n  ${0:someUrl} = ts.URL\n# test error\nsnippet ter\nabbr if err != nil { t.Errorf(...) }\n  if err != nil {\n    t.Errorf(\"${1}\")\n  }\n# test fatal error\nsnippet terf\nabbr if err != nil { t.Fatalf(...) }\n  if err != nil {\n    t.Fatalf(\"${1}\")\n  }\n# test example\nsnippet example\n\tfunc Example${1:Method}() {\n\t\t${0}\n\t\t// Output:\n\t}\n# test benchmark\nsnippet benchmark\n\tfunc Benchmark${1:Method}(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t${0}\n\t\t}\n\t}\n# variable declaration\nsnippet var\nabbr var x Type [= ...]\n\tvar ${1:x} ${2:Type}${3: = ${0:value\\}}\n# variables declaration\nsnippet vars\nabbr var ( ... )\n\tvar (\n\t\t${1:x} ${2:Type}${3: = ${0:value\\}}\n\t)\n# equals fails the test if exp is not equal to act.\nsnippet eq\nabbr equals: test two identifiers with DeepEqual\n  if !reflect.DeepEqual(${1:expected}, ${2:actual}) {\n  \t_, file, line, _ := runtime.Caller(0)\n  \tfmt.Printf(\"%s:%d:\\n\\n\\texp: %#v\\n\\n\\tgot: %#v\\n\\n\", filepath.Base(file), line, $1, $2)\n  \tt.FailNow()\n  }\n\nsnippet hf\nabbr http.HandlerFunc\n  func ${1:handler}(w http.ResponseWriter, r *http.Request) {\n    ${0:fmt.Fprintf(w, \"hello world\")}\n  }\n\nsnippet hhf\nabbr mux.HandleFunc(...)\n  ${1:http}.HandleFunc(\"${2:/}\", func(w http.ResponseWriter, r *http.Request) {\n    ${0:fmt.Fprintf(w, \"hello world\")}\n  })\n"
  },
  {
    "path": "indent/go.vim",
    "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\" indent/go.vim: Vim indent file for Go.\n\"\n\" TODO:\n\" - function invocations split across lines\n\" - general line splits (line ends in an operator)\n\nif exists(\"b:did_indent\")\n  finish\nendif\nlet b:did_indent = 1\n\n\" C indentation is too far off useful, mainly due to Go's := operator.\n\" Let's just define our own.\nsetlocal nolisp\nsetlocal autoindent\nsetlocal indentexpr=GoIndent(v:lnum)\nsetlocal indentkeys+=<:>,0=},0=)\n\nif exists(\"*GoIndent\")\n  finish\nendif\n\n\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! GoIndent(lnum) abort\n  let prevlnum = prevnonblank(a:lnum-1)\n  if prevlnum == 0\n    \" top of file\n    return 0\n  endif\n\n  \" grab the previous and current line, stripping comments.\n  let prevl = substitute(getline(prevlnum), '//.*$', '', '')\n  let thisl = substitute(getline(a:lnum), '//.*$', '', '')\n  let previ = indent(prevlnum)\n\n  let ind = previ\n\n  for synid in synstack(a:lnum, 1)\n    if synIDattr(synid, 'name') == 'goRawString'\n      if prevl =~ '\\%(\\%(:\\?=\\)\\|(\\|,\\)\\s*`[^`]*$'\n        \" previous line started a multi-line raw string\n        return 0\n      endif\n      \" return -1 to keep the current indent.\n      return -1\n    endif\n  endfor\n\n  if prevl =~ '[({]\\s*$'\n    \" previous line opened a block\n    let ind += shiftwidth()\n  endif\n  if prevl =~# '^\\s*\\(case .*\\|default\\):$'\n    \" previous line is part of a switch statement\n    let ind += shiftwidth()\n  endif\n  \" TODO: handle if the previous line is a label.\n\n  if thisl =~ '^\\s*[)}]'\n    \" this line closed a block\n    let ind -= shiftwidth()\n  endif\n\n  \" Colons are tricky.\n  \" We want to outdent if it's part of a switch (\"case foo:\" or \"default:\").\n  \" We ignore trying to deal with jump labels because (a) they're rare, and\n  \" (b) they're hard to disambiguate from a composite literal key.\n  if thisl =~# '^\\s*\\(case .*\\|default\\):$'\n    let ind -= shiftwidth()\n  endif\n\n  return ind\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "indent/gohtmltmpl.vim",
    "content": "if exists(\"b:did_indent\")\n  finish\nendif\n\nruntime! indent/html.vim\n\n\" Indent Golang HTML templates\nsetlocal indentexpr=GetGoHTMLTmplIndent(v:lnum)\nsetlocal indentkeys+==else,=end\n\n\" Only define the function once.\nif exists(\"*GetGoHTMLTmplIndent\")\n  finish\nendif\n\n\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! GetGoHTMLTmplIndent(lnum)\n  \" Get HTML indent\n  if exists('*HtmlIndent')\n    let ind = HtmlIndent()\n  else\n    let ind = HtmlIndentGet(a:lnum)\n  endif\n\n  \" The value of a single shift-width\n  if exists('*shiftwidth')\n    let sw = shiftwidth()\n  else\n    let sw = &sw\n  endif\n\n  \" If need to indent based on last line\n  let last_line = getline(a:lnum-1)\n  if last_line =~ '^\\s*{{-\\=\\s*\\%(if\\|else\\|range\\|with\\|define\\|block\\).*}}'\n    let ind += sw\n  endif\n\n  \" End of FuncMap block\n  let current_line = getline(a:lnum)\n  if current_line =~ '^\\s*{{-\\=\\s*\\%(else\\|end\\).*}}'\n    let ind -= sw\n  endif\n\n  return ind\nendfunction\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "plugin/go.vim",
    "content": "\" install necessary Go tools\nif exists(\"g:go_loaded_install\")\n  finish\nendif\nlet g:go_loaded_install = 1\n\n\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nfunction! s:checkVersion() abort\n  let l:unsupported = 0\n  if go#config#VersionWarning() != 0\n    if has('nvim')\n      let l:unsupported = !has('nvim-0.4.0')\n    else\n      let l:unsupported = !has('patch-8.2.5072')\n    endif\n\n    if l:unsupported == 1\n      echohl Error\n      echom \"vim-go requires at least Vim 8.2.5072 or Neovim 0.4.0, but you're using an older version.\"\n      echom \"Please update your Vim for the best vim-go experience.\"\n      echom \"If you really want to continue you can set this to make the error go away:\"\n      echom \"    let g:go_version_warning = 0\"\n      echom \"Note that some features may error out or behave incorrectly.\"\n      echom \"Please do not report bugs unless you're using at least Vim 8.2.5072 or Neovim 0.4.0.\"\n      echohl None\n\n      \" Make sure people see this.\n      sleep 2\n    endif\n  endif\nendfunction\n\ncall s:checkVersion()\n\n\" these packages are used by vim-go and can be automatically installed if\n\" needed by the user with GoInstallBinaries.\n\n\" NOTE(bc): varying the binary name and the tail of the import path does not yet work in module aware mode.\nlet s:packages = {\n      \\ 'asmfmt':        ['github.com/klauspost/asmfmt/cmd/asmfmt@latest'],\n      \\ 'dlv':           ['github.com/go-delve/delve/cmd/dlv@latest'],\n      \\ 'errcheck':      ['github.com/kisielk/errcheck@latest'],\n      \\ 'fillstruct':    ['github.com/davidrjenni/reftools/cmd/fillstruct@master'],\n      \\ 'godef':         ['github.com/rogpeppe/godef@latest'],\n      \\ 'goimports':     ['golang.org/x/tools/cmd/goimports@master'],\n      \\ 'revive':        ['github.com/mgechev/revive@latest'],\n      \\ 'gopls':         ['golang.org/x/tools/gopls@latest', {}, {'after': function('go#lsp#Restart', [])}],\n      \\ 'golangci-lint': ['github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest'],\n      \\ 'staticcheck':   ['honnef.co/go/tools/cmd/staticcheck@latest'],\n      \\ 'gomodifytags':  ['github.com/fatih/gomodifytags@latest'],\n      \\ 'gotags':        ['github.com/jstemmer/gotags@master'],\n      \\ 'impl':          ['github.com/josharian/impl@main'],\n      \\ 'motion':        ['github.com/fatih/motion@latest'],\n      \\ 'iferr':         ['github.com/koron/iferr@master'],\n\\ }\n\n\" These commands are available on any filetypes\ncommand! -nargs=* -complete=customlist,s:complete GoInstallBinaries call s:GoInstallBinaries(-1, <f-args>)\ncommand! -nargs=* -complete=customlist,s:complete GoUpdateBinaries  call s:GoInstallBinaries(1, <f-args>)\ncommand! -nargs=? -complete=dir GoPath call go#path#GoPath(<f-args>)\n\nfun! s:complete(lead, cmdline, cursor)\n  return filter(keys(s:packages), 'strpart(v:val, 0, len(a:lead)) == a:lead')\nendfun\n\n\" GoInstallBinaries downloads and installs binaries defined in s:packages to\n\" $GOBIN or $GOPATH/bin. GoInstallBinaries will update already installed\n\" binaries only if updateBinaries = 1. By default, all packages in s:packages\n\" will be installed, but the set can be limited by passing the desired\n\" packages in the unnamed arguments.\nfunction! s:GoInstallBinaries(updateBinaries, ...)\n  let err = s:CheckBinaries()\n  if err != 0\n    return\n  endif\n\n  if go#path#Default() == \"\"\n    call go#util#EchoError('$GOPATH is not set and `go env GOPATH` returns empty')\n    return\n  endif\n\n  let go_bin_path = go#path#BinPath()\n\n  let [l:goos, l:goarch] = go#util#hostosarch()\n  let Restore_goos = go#util#SetEnv('GOOS', l:goos)\n  let Restore_goarch = go#util#SetEnv('GOARCH', l:goarch)\n\n  \" change $GOBIN so go can automatically install to it\n  let Restore_gobin = go#util#SetEnv('GOBIN', go_bin_path)\n\n  \" vim's executable path is looking in PATH so add our go_bin path to it\n  let Restore_path = go#util#SetEnv('PATH', go_bin_path . go#util#PathListSep() . $PATH)\n\n  \" when shellslash is set on MS-* systems, shellescape puts single quotes\n  \" around the output string. cmd on Windows does not handle single quotes\n  \" correctly. Unsetting shellslash forces shellescape to use double quotes\n  \" instead.\n  let resetshellslash = 0\n  if has('win32') && &shellslash\n    let resetshellslash = 1\n    set noshellslash\n  endif\n\n  let l:get_base_cmd = ['go', 'install', '-v', '-mod=mod']\n\n  \" Filter packages from arguments (if any).\n  let l:packages = {}\n  if a:0 > 0\n    for l:bin in a:000\n      let l:version = substitute(l:bin, '.*@', '', '')\n      if l:version == l:bin\n        let l:version = ''\n      endif\n      let l:bin = substitute(l:bin, '@.*', '', '')\n\n      let l:pkg = get(s:packages, l:bin, [])\n      if len(l:pkg) == 0\n        call go#util#EchoError('unknown binary: ' . l:bin)\n        return\n      endif\n\n      if l:version isnot ''\n        let l:pkg[0] = substitute(l:pkg[0], '@\\zs.*', l:version, '')\n      endif\n      let l:packages[l:bin] = l:pkg\n    endfor\n  else\n    let l:packages = s:packages\n  endif\n\n  let l:platform = ''\n  if go#util#IsWin()\n    let l:platform = 'windows'\n  endif\n\n  let l:oldmore = &more\n  let &more = 0\n\n  let Restore_modules = go#util#SetEnv('GO111MODULE', 'on')\n  for [l:binary, l:pkg] in items(l:packages)\n    let l:importPath = l:pkg[0]\n\n    \" TODO(bc): how to support this with modules? Do we have to clone and then\n    \" install manually? Probably not. I suspect that we can just use GOPATH\n    \" mode and then do the legacy method.\n    let bin_setting_name = \"go_\" . l:binary . \"_bin\"\n\n    let l:extension = ''\n    if go#util#IsWin()\n      let l:extension = '.exe'\n    endif\n\n    let bin = get(g:, bin_setting_name, l:binary . l:extension)\n\n    if !executable(bin) || a:updateBinaries == 1\n      if a:updateBinaries == 1\n        echo \"vim-go: Updating \" . l:binary . \". Reinstalling \". importPath . \" to folder \" . go_bin_path\n      else\n        echo \"vim-go: \". l:binary .\" not found. Installing \". importPath . \" to folder \" . go_bin_path\n      endif\n\n      let l:tmpdir = go#util#tempdir('vim-go')\n      try\n        let l:dir = go#util#Chdir(l:tmpdir)\n        let l:get_cmd = copy(l:get_base_cmd)\n\n        if len(l:pkg) > 1 && get(l:pkg[1], l:platform, []) isnot []\n          let l:get_cmd += get(l:pkg[1], l:platform, [])\n        endif\n\n        \" TODO(bc): how to install the bin to a different name than the binary\n        \" path? go install does not support -o\n        \"let l:get_cmd += ['-o', printf('%s%s%s', go_bin_path, go#util#PathSep(), bin)]\n\n        let [l:out, l:err] = go#util#Exec(l:get_cmd + [l:importPath])\n        if l:err\n          call go#util#EchoError(printf('Error installing %s: %s', l:importPath, l:out))\n        endif\n      finally\n        call go#util#Chdir(l:dir)\n      endtry\n\n      if len(l:pkg) > 2\n        call call(get(l:pkg[2], 'after', function('s:noop', [])), [])\n      endif\n    endif\n  endfor\n\n  \" restore back!\n  call call(Restore_modules, [])\n  call call(Restore_path, [])\n  call call(Restore_gobin, [])\n  call call(Restore_goarch, [])\n  call call(Restore_goos, [])\n\n  if resetshellslash\n    set shellslash\n  endif\n\n  if a:updateBinaries == 1\n    call go#util#EchoInfo('updating finished!')\n  else\n    call go#util#EchoInfo('installing finished!')\n  endif\n\n  let &more = l:oldmore\nendfunction\n\n\" CheckBinaries checks if the necessary binaries to install the Go tool\n\" commands are available.\nfunction! s:CheckBinaries()\n  if !executable('go')\n    call go#util#EchoError('go executable not found.')\n    return -1\n  endif\n\n  if !executable('git')\n    call go#util#EchoError('git executable not found.')\n    return -1\n  endif\nendfunction\n\n\" Autocommands\n\" ============================================================================\n\"\n\n\" We take care to preserve the user's fileencodings and fileformats,\n\" because those settings are global (not buffer local), yet we want\n\" to override them for loading Go files, which are defined to be UTF-8.\nlet s:current_fileformats = ''\nlet s:current_fileencodings = ''\n\n\" define fileencodings to open as utf-8 encoding even if it's ascii.\nfunction! s:gofiletype_pre()\n  let s:current_fileformats = &g:fileformats\n  let s:current_fileencodings = &g:fileencodings\n  set fileencodings=utf-8 fileformats=unix\nendfunction\n\n\" restore fileencodings as others\nfunction! s:gofiletype_post()\n  let &g:fileformats = s:current_fileformats\n  let &g:fileencodings = s:current_fileencodings\nendfunction\n\nfunction! s:register()\n  if !(&modifiable && expand('<amatch>') ==# 'go')\n    return\n  endif\n\n  \" Resolve any symlinks in <afile> so that the filename will match what Vim\n  \" will ultimately and usually produce.\n  call go#lsp#DidOpen(resolve(expand('<afile>:p')))\nendfunction\n\nfunction! s:noop(...) abort\nendfunction\n\naugroup vim-go\n  autocmd!\n\n  autocmd BufNewFile *.go if &modifiable | setlocal fileencoding=utf-8 fileformat=unix | endif\n  autocmd BufNewFile *.go call go#auto#template_autocreate()\n  autocmd BufRead *.go call s:gofiletype_pre()\n  autocmd BufReadPost *.go call s:gofiletype_post()\n\n  autocmd BufNewFile *.s if &modifiable | setlocal fileencoding=utf-8 fileformat=unix | endif\n  autocmd BufRead *.s call s:gofiletype_pre()\n  autocmd BufReadPost *.s call s:gofiletype_post()\n\n  if go#util#has_job()\n    autocmd FileType * call s:register()\n  endif\naugroup end\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "rplugin/python3/denite/source/decls.py",
    "content": "# ============================================================================\n# FILE: decls.py\n# AUTHOR: delphinus <delphinus@remora.cx>\n# License: MIT license\n# ============================================================================\n\nimport os\nimport subprocess\nimport json\nimport denite.util\nfrom .base import Base\n\nDECLS_SYNTAX_HIGHLIGHT = [\n    {'name': 'FilePath', 're': r'[^:]*\\ze:', 'link': 'Comment'},\n    {'name': 'Line', 're': r'\\d\\+\\ze :', 'link': 'LineNr'},\n    {'name': 'WholeFunction', 're': r'\\vfunc %(\\([^)]+\\) )?[^(]+'},\n    {'name': 'Function', 'parent': 'WholeFunction',\n     're': r'\\S\\+\\ze(', 'link': 'Function'},\n    {'name': 'WholeType', 're': r'type \\S\\+'},\n    {'name': 'Type', 'parent': 'WholeType',\n     're': r'\\v( )@<=\\S+', 'link': 'Type'},\n    {'name': 'Separator', 're': r':', 'conceal': True},\n    {'name': 'SeparatorFunction', 'parent': 'WholeFunction',\n     're': r'func ', 'conceal': True},\n    {'name': 'SeparatorType', 'parent': 'WholeType',\n     're': r'type ', 'conceal': True},\n    ]\n\n\nclass Source(Base):\n\n    def __init__(self, vim):\n        super().__init__(vim)\n\n        self.name = 'decls'\n        self.kind = 'file'\n\n    def gather_candidates(self, context):\n        bin_path = self.vim.call('go#path#CheckBinPath', 'motion')\n        if bin_path == '':\n            return []\n\n        expand = context['args'][0] if context['args'] else '%:p:h'\n        target = self.vim.funcs.expand(expand)\n\n        if os.path.isdir(target):\n            mode = 'dir'\n        elif os.path.isfile(target):\n            mode = 'file'\n        else:\n            return []\n\n        if self.vim.funcs.exists('g:go_decls_includes'):\n            include = self.vim.eval('g:go_decls_includes')\n        else:\n            include = 'func,type'\n\n        command = [bin_path, '-mode', 'decls', '-include', include,\n                   '-' + mode, target]\n\n        try:\n            cmd = subprocess.run(command, stdout=subprocess.PIPE, check=True)\n        except subprocess.CalledProcessError as err:\n            denite.util.error(self.vim,\n                              'command returned invalid response: ' + str(err))\n            return []\n\n        txt = cmd.stdout.decode('utf-8')\n        output = json.loads(txt)\n\n        def make_candidates(row):\n            name = self.vim.funcs.fnamemodify(row['filename'], ':~:.')\n            return {\n                'word': '{0} :{1} :{2}'.format(name, row['line'], row['full']),\n                'action__path': row['filename'],\n                'action__line': row['line'],\n                'action__col': row['col'],\n                }\n        return list(map(make_candidates, output['decls']))\n\n    def highlight(self):\n        for syn in DECLS_SYNTAX_HIGHLIGHT:\n            containedin = self.syntax_name\n            containedin += '_' + syn['parent'] if 'parent' in syn else ''\n            conceal = ' conceal' if 'conceal' in syn else ''\n\n            self.vim.command(\n                'syntax match {0}_{1} /{2}/ contained containedin={3}{4}'\n                .format(self.syntax_name, syn['name'], syn['re'],\n                        containedin, conceal))\n\n            if 'link' in syn:\n                self.vim.command('highlight default link {0}_{1} {2}'.format(\n                    self.syntax_name, syn['name'], syn['link']))\n"
  },
  {
    "path": "scripts/bench-syntax",
    "content": "#!/bin/sh\n#\n# Benchmark the syntax/go.vim file.\n#\n# The first argument is the Vim version to test (as in run-vim), the rest of the\n# agument are g:go_highlight_* settings (without that prefix). You can use \"ALL\"\n# to set all the options.\n#\n\nset -euC\nvimgodir=$(cd -P \"$(dirname \"$0\")/..\" > /dev/null && pwd)\ncd \"$vimgodir\"\n\nif [ -z \"${1:-}\" ]; then\n  echo \"unknown version: '${1:-}'\"\n  echo \"First argument must be 'vim-8.2', 'vim-9.1', or 'nvim'.\"\n  exit 1\nfi\n\nif [ -z \"${2:-}\" ]; then\n  echo \"file not set\"\n  echo \"Second argument must be a Go file to benchmark, as 'filename:linenr'\"\n  exit 1\nfi\n\nvim=$1\nfile=\"$(echo \"$2\" | cut -d : -f 1)\"\nline=\"$(echo \"$2\" | cut -d : -f 2)\"\nif [ -z \"$line\" -o \"$line\" = \"$file\" ]; then\n  echo \"Second argument must be a Go file to benchmark, as 'filename:linenr'\"\n  exit 1\nfi\n\nshift; shift\nexport RUNBENCH_SETTINGS=$@\nexport RUNBENCH_OUT=\"$(mktemp -p \"${TMPDIR:-/tmp}\" vimgo-bench.XXXXX)\"\n\n\"$vimgodir/scripts/run-vim\" $vim \\\n  +\"silent e $file\" \\\n  +\"normal! ${line}G\" \\\n  -S ./scripts/runbench.vim\n\necho \"Report written to:\"\necho \"$RUNBENCH_OUT\"\n"
  },
  {
    "path": "scripts/docker-test",
    "content": "#!/bin/sh\n#\n# Run all tests inside a Docker container\n#\n\nset -euC\nvimgodir=$(cd -P \"$(dirname \"$0\")/..\" > /dev/null && pwd)\ncd \"$vimgodir\"\n\ndocker build --platform=linux/amd64 --tag vim-go-test .\n# seccomp=confined is required for dlv to run in a container, hence it's\n# required for vim-go's debug tests.\ndocker run -e VIMS --rm --security-opt=\"seccomp=unconfined\" vim-go-test\n\n# vim:ts=2:sts=2:sw=2:et\n"
  },
  {
    "path": "scripts/install-tools",
    "content": "#!/bin/sh\n#\n# Install and setup a Vim or Neovim for running tests.\n# This should work on both GitHub Actions and people's desktop computers, and\n# be 100% independent from any system installed Vim.\n#\n\nset -euC\n\nvimgodir=$(cd -P \"$(dirname \"$0\")/..\" > /dev/null && pwd)\ncd \"$vimgodir\"\n\nvim=${1:-}\n\ninstalldir=\"/tmp/vim-go-test/$1-install\"\n\n# Make sure all Go tools and other dependencies are installed.\necho \"Installing Go binaries\"\nexport GOPATH=$installdir\nexport GO111MODULE=on\nexport PATH=\"${GOPATH}/bin:$PATH\"\n\"$vimgodir/scripts/run-vim\" $vim +':silent :GoUpdateBinaries' +':qa'\n\necho \"Installing lint tools\"\n(\n  mkdir -p \"$installdir/share/vim/vimgo/pack/vim-go/start/\"\n  cd \"$installdir/share/vim/vimgo/pack/vim-go/start/\"\n  [ -d \"vim-vimhelplint\" ] || git clone --depth 1 --quiet https://github.com/machakann/vim-vimhelplint\n  [ -d \"vim-vimlparser\" ]  || git clone --depth 1 --quiet https://github.com/ynkdir/vim-vimlparser\n  [ -d \"vim-vimlint\" ]     || git clone --depth 1 --quiet https://github.com/syngan/vim-vimlint\n  sed -e 's/^#set -x/set -x/g' -e 's/\\<egrep\\>/grep -E/g'  vim-vimlint/bin/vimlint.sh > vim-vimlint/bin/vimlint-grep.sh\n  chmod ugo+x vim-vimlint/bin/vimlint-grep.sh\n)\n\necho \"vim-go tools installed to: $installdir/share/vim/vimgo/pack/vim-go/start\"\n\n# vim:ts=2:sts=2:sw=2:et\n"
  },
  {
    "path": "scripts/install-vim",
    "content": "#!/bin/sh\n#\n# Install and setup a Vim or Neovim for running tests.\n# This should work on both GitHub Actions and people's desktop computers, and\n# be 100% independent from any system installed Vim.\n#\n# It will echo the full path to a Vim binary, e.g.:\n#   /some/path/src/vim\n\nset -euC\n\nvimgodir=$(cd -P \"$(dirname \"$0\")/..\" > /dev/null && pwd)\ncd \"$vimgodir\"\n\nvim=${1:-}\n\ncase \"$vim\" in\n  \"vim-8.2\")\n    # This follows the version in Ubuntu LTS. Vim's master branch isn't always\n    # stable, and we don't want to have the build fail because Vim introduced a\n    # bug.\n    # Currently, 8.2.5072 is actually the greatest patch number applied in the\n    # vim installed by Ubuntu 22.04 LTS's package, so arguably v8.2.5072 should\n    # be used here, but there's a fix in v8.2.5135 that we need to compile on\n    # trixie and the distance between 8.2.5072 and 8.2.5135 is not too great,\n    # so use that instead.\n    # ref: https://stackoverflow.com/a/79376005\n    tag=\"v8.2.5135\"\n    giturl=\"https://github.com/vim/vim\"\n\n    ;;\n\n  \"vim-9.1\")\n    # This is the version that's installed by homebrew currently. It doesn't\n    # have to stay up to date with homebrew, and is only chosen here because\n    # that's what homebrew was using at the the time and we need a version to\n    # vimlint with.\n    tag=\"v9.1.1300\"\n    giturl=\"https://github.com/vim/vim\"\n    ;;\n\n  \"nvim\")\n    # Use latest stable version.\n    tag=\"v0.9.1\"\n    giturl=\"https://github.com/neovim/neovim\"\n    ;;\n\n  *)\n    echo \"unknown version: '${1:-}'\"\n    echo \"First argument must be 'vim-8.1', vim-8.2, or 'nvim'.\"\n    exit 1\n    ;;\nesac\n\nsrcdir=\"/tmp/vim-go-test/$1-src\"\ninstalldir=\"/tmp/vim-go-test/$1-install\"\n\n# Use cached installdir.\nif [ -d \"$installdir\" ]; then\n  echo \"$installdir exists; skipping build.\"\n\n  # The ./scripts/test script relies on this.\n  echo \"installed to: $installdir\"\n  exit 0\nfi\n\nmkdir -p \"$srcdir\"\ncd \"$srcdir\"\n\n# Neovim build requires more deps than Vim and is annoying, so we use the\n# binary.\n# 0.2.0 doesn't have a binary build for Linux, so we use 0.2.1-dev for now.\nif [ \"$1\" = \"nvim\" ]; then\n\n  # TODO: Use macOS binaries on macOS\n  curl -Ls https://github.com/neovim/neovim/releases/download/$tag/nvim-linux64.tar.gz |\n    tar xzf - -C /tmp/vim-go-test/\n  mv /tmp/vim-go-test/nvim-linux64 /tmp/vim-go-test/nvim-install\n  mkdir -p \"$installdir/share/nvim/runtime/pack/vim-go/start\"\n  ln -s \"$vimgodir\" \"$installdir/share/nvim/runtime/pack/vim-go/start/vim-go\"\n\n  # Consistent paths makes calling things easier.\n  mv \"$installdir/bin/nvim\" \"$installdir/bin/vim\"\n  mkdir -p \"$installdir/share/vim/vimgo/pack\"\n  ln -s \"$installdir/share/nvim/runtime/pack/vim-go\" \"$installdir/share/vim/vimgo/pack/vim-go\"\n\n# Build Vim from source.\nelse\n  if [ -d \"$srcdir/.git\" ]; then\n    echo \"Skipping clone as $srcdir/.git exists\"\n  else\n    echo \"Cloning $tag from $giturl\"\n    git clone --branch \"$tag\" --depth 1 \"$giturl\" \"$srcdir\"\n  fi\n\n  ./configure --prefix=\"$installdir\" --with-features=huge --disable-gui\n  make install\n  mkdir -p \"$installdir/share/vim/vimgo/pack/vim-go/start\"\n  ln -s \"$vimgodir\" \"$installdir/share/vim/vimgo/pack/vim-go/start/vim-go\"\nfi\n\n# Don't really need source after successful install.\nrm -rf \"$srcdir\"\n\necho \"installed to: $installdir\"\n\n# vim:ts=2:sts=2:sw=2:et\n"
  },
  {
    "path": "scripts/lint",
    "content": "#!/bin/sh\n#\n# Run all linting tools.\n#\n\nset -euC\nvimgodir=$(cd -P \"$(dirname \"$0\")/..\" > /dev/null && pwd)\ncd \"$vimgodir\"\n\n### Setup Vim and other dependencies.\n#####################################\nif [ -z \"${1:-}\" ]; then\n  printf \"unknown version: '%s'\\n\" \"${1:-}\" >&2\n  printf \"First argument must be 'vim-8.2', 'vim-9.1' or 'nvim'.\\n\" >&2\n  exit 1\nfi\n\nvim=$1\nvimdir=\"/tmp/vim-go-test/$vim-install\"\nexport GOPATH=$vimdir\nexport PATH=\"${GOPATH}/bin:$PATH\"\n\nif [ ! -f \"$vimdir/bin/vim\" ]; then\n  printf \"%s/bin/vim doesn't exist; did you install it with the install-vim script?\\n\" \"$vimdir\" >&2\n  exit 1\nfi\n\n### Run vint\n############\nfailed=0\nprintf \"Running vint ... \" >&2\nif [ -x \"$(command -v vint)\" ]; then\n  lint=$(vint \"$vimgodir\" 2>&1 ||:)\n  if [ -n \"$lint\" ]; then\n    printf \"FAILED\\n\" >&2\n    printf \"$lint\" >&2\n    printf \"\\n\" >&2\n    # set failed to 3, because exit code 2 is used by python to indicate a problem running a command.\n    failed=3\n  else\n    printf \"PASSED\\n\" >&2\n  fi\nelse\n  printf \"SKIPPED\\n\" >&2\n  printf \"vint binary not found; use 'pip install vim-vint' to install it.\\n\" >&2\nfi\n\n### Run vim-vimlint\n###################\nprintf \"Running vim-vimlint ... \" >&2\nset +e\nlint=$(export VIMLINT_VIM='vim +\"set maxfuncdepth=200\"'; sh \"$vimdir/share/vim/vimgo/pack/vim-go/start/vim-vimlint/bin/vimlint-grep.sh\" \\\n  -p \"$vimdir/share/vim/vimgo/pack/vim-go/start/vim-vimlparser\" \\\n  -l \"$vimdir/share/vim/vimgo/pack/vim-go/start/vim-vimlint\" \\\n  -u \\\n  -c func_abort=1 \\\n  -e EVL110=1 -e EVL103=1 -e EVL104=1 -e EVL102=1 \\\n  \"$vimgodir\" \\\n  2>&1)\nresult=\"$?\"\nset -e\nif [ \"$result\" -eq \"2\" ]; then\n  printf \"FAILED\\n\" >&2\n  printf \"$lint\" >&2\n  printf \"\\n\" >&2\n  failed=4\nelif [ \"$result\" -ne \"0\" ]; then\n  printf \"FAILED\\n\" >&2\n  printf \"$lint\" >&2\n  printf \"\\n\" >&2\nelse\n  printf \"PASSED\\n\" >&2\nfi\n\n### Run vimhelplint.\n####################\nprintf \"Running vimhelplint ... \" >&2\n\n# set modeline explicitly so that the modeline will be respected when run as root.\nlint=$($vimdir/bin/vim -esNR \\\n  --cmd \"set rtp+=$vimdir/share/vim/vimgo/pack/vim-go/start/vim-vimhelplint/\" \\\n  --cmd 'set modeline' \\\n  +'filetype plugin on' \\\n  +\"e $vimgodir/doc/vim-go.txt\" \\\n  +'verbose VimhelpLintEcho' \\\n  +q \\\n  2>&1 ||:)\nif [ \"$lint\" ]; then\n  printf \"FAILED\\n\" >&2\n  printf \"$lint\" >&2\n  failed=5\nelse\n  printf \"PASSED\\n\" >&2\nfi\n\nexit \"$failed\"\n"
  },
  {
    "path": "scripts/run-vim",
    "content": "#!/bin/sh\n#\n# Run a \"bare\" Vim with just vim-go and ignoring ~/.vim\n#\n\nset -euC\nvimgodir=$(cd -P \"$(dirname \"$0\")/..\" > /dev/null && pwd)\ncd \"$vimgodir\"\n\ncoverage=0\nwhile getopts \"c\" option; do\n  case \"$option\" in\n      c) coverage=1; ;;\n  esac\ndone\nshift $((OPTIND - 1))\n\nif [ -z \"${1:-}\" ]; then\n  echo \"unknown version: '${1:-}'\"\n  echo \"First argument must be 'vim-8.2', 'vim-9.1', or 'nvim'.\"\n  exit 1\nfi\n\ndir=\"/tmp/vim-go-test/$1-install\"\nexport GOPATH=$dir\nexport GO111MODULE=on\nexport PATH=\"${GOPATH}/bin:$PATH\"\nshift\n\nif [ ! -f \"$dir/bin/vim\" ]; then\n  echo \"$dir/bin/vim doesn't exist; did you install it with the install-vim script?\"\n  exit 1\nfi\n\nif [ $coverage -eq 1 ]; then\n  covimerage -q run --report-file /tmp/vim-go-test/cov-profile.txt --append \\\n    $dir/bin/vim --noplugin -u NONE -i NONE -N -n \\\n      +\"set shm+=WAFI rtp^=$vimgodir packpath=$dir/share/vim/vimgo\" \\\n      +'filetype plugin indent on' \\\n      +'packloadall!' \\\n      \"$@\"\nelse\n  $dir/bin/vim --noplugin -u NONE -i NONE -N -n \\\n    +\"set shm+=WAFI rtp^=$vimgodir packpath=$dir/share/vim/vimgo\" \\\n    +'filetype plugin indent on' \\\n    +'packloadall!' \\\n    \"$@\"\nfi\n\n\n# vim:ts=2:sts=2:sw=2:et\n"
  },
  {
    "path": "scripts/runbench.vim",
    "content": "\" vint: -ProhibitSetNoCompatible\n\n\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nset nocompatible nomore shellslash encoding=utf-8 shortmess+=WIF\nlang mess C\n\nif $RUNBENCH_SETTINGS is? 'all'\n  let $RUNBENCH_SETTINGS = join(['array_whitespace_error', 'build_constraints',\n        \\ 'chan_whitespace_error', 'extra_types', 'fields', 'format_strings',\n        \\ 'function_arguments', 'function_calls', 'functions', 'generate_tags',\n        \\ 'operators', 'space_tab_error', 'string_spellcheck',\n        \\ 'trailing_whitespace_error', 'types', 'variable_assignments',\n        \\ 'variable_declarations'], ' ')\nendif\n\nfor s:s in split($RUNBENCH_SETTINGS, ' ')\n  call execute('let g:go_highlight_' . s:s . ' = 1')\nendfor\n\nfiletype plugin indent on\nsyntax on\n\nsyntime on\nredraw!\nlet s:report = execute('syntime report')\nexecute ':e ' . fnameescape($RUNBENCH_OUT)\ncall setline('.', split(s:report, '\\n'))\nwq\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "scripts/runtest.vim",
    "content": "\" Make sure some options are set to sane defaults and output all messages in\n\" English.\n\n\" vint: -ProhibitSetNoCompatible\n\n\" don't spam the user when Vim is started in Vi compatibility mode\nlet s:cpo_save = &cpo\nset cpo&vim\n\nset nocompatible nomore shellslash encoding=utf-8 shortmess+=WIF\nlang mess C\n\n\" Initialize variables.\nlet s:total_started = reltime()\nlet s:fail = 0\nlet s:done = 0\nlet s:logs = []\nlet s:gopath = $GOPATH\nif !exists('g:test_verbose')\n  let g:test_verbose = 0\nendif\n\nfunction! s:logmessages() abort\n  \" Add all messages (usually errors).\n  redir => s:mess\n    silent messages\n  redir END\n  let s:logs = s:logs + filter(split(s:mess, \"\\n\"), 'v:val !~ \"^Messages maintainer\"')\n  silent messages clear\nendfunction\n\nfunction! s:clearOptions() abort\n  \" clear all the vim-go options\n  for l:k in keys(g:)\n    if l:k =~ '^go_' && l:k !~ '^go_loaded_'\n      call execute(printf('unlet g:%s', l:k))\n    endif\n  endfor\nendfunction\n\n\" Source the passed test file.\nsource %\n\n\" cd into the folder of the test file.\nlet s:testfile = expand('%:t')\nlet s:dir = expand('%:p:h')\ncall go#util#Chdir(s:dir)\n\n\" Export root path to vim-go dir.\nlet g:vim_go_root = fnamemodify(getcwd(), ':p')\n\n\" Get a list of all Test_ functions for the given file.\nredir @q\n  silent function /^Test_\nredir END\nlet s:tests = split(substitute(@q, 'function \\(\\k\\+()\\)', '\\1', 'g'))\n\n\" log any messages already accumulated.\ncall s:logmessages()\n\" Iterate over all tests and execute them.\nfor s:test in sort(s:tests)\n  \" Since we extract the tests from a regexp the \"abort\" keyword is also in\n  \" the list, which is not a test name :-)\n  if s:test == 'abort'\n    continue\n  endif\n\n  \" make sure g:go_echo_command_info is not set so that we don't get\n  \" unexpected messages when commands are executed.\n  let g:go_echo_command_info = 0\n\n  \" make sure gopls doesn't use multi-client mode; there seem to be some racy\n  \" conditions when trying to shutdown the server after each test when\n  \" multi-client mode is used.\n  let g:go_gopls_options = []\n\n  let s:started = reltime()\n  if g:test_verbose is 1\n    call add(s:logs, printf(\"=== RUN  %s\", s:test[:-3]))\n  endif\n  try\n    exe 'call ' . s:test\n    \" sleep to give events a chance to be processed. This is especially\n    \" important for the LSP code to have a chance to run before Vim exits,  in\n    \" order to avoid errors trying to write to the gopls channels since Vim\n    \" would otherwise stop gopls before the event handlers were run and result\n    \" in 'stream closed' errors when the events were run _after_ gopls exited.\n    sleep 50m\n  catch\n    call assert_report(printf('at %s: %s', v:throwpoint, v:exception))\n  endtry\n\n  let s:elapsed_time = substitute(reltimestr(reltime(s:started)), '^\\s*\\(.\\{-}\\)\\s*$', '\\1', '')\n\n  \" Restore GOPATH after each test.\n  let $GOPATH = s:gopath\n  \" Restore the working directory after each test.\n  call go#util#Chdir(s:dir)\n\n  try\n    \" exit gopls after each test\n    call go#lsp#Exit()\n  catch /^Vim(call):E900: Invalid channel id/\n    \" do nothing - gopls has stopped\n  finally\n    call s:clearOptions()\n  endtry\n\n  let s:done += 1\n\n  if len(v:errors) > 0\n    let s:fail += 1\n    call add(s:logs, printf(\"--- FAIL %s (%ss)\", s:test[:-3], s:elapsed_time))\n    call s:logmessages()\n    call extend(s:logs, map(v:errors, '\"        \".  v:val'))\n\n    \" Reset so we can capture failures of the next test.\n    let v:errors = []\n  else\n    if g:test_verbose is 1\n      call s:logmessages()\n      call add(s:logs, printf(\"--- PASS %s (%ss)\", s:test[:-3], s:elapsed_time))\n    else\n      silent messages clear\n    endif\n  endif\nendfor\n\n\" Create an empty fail to indicate that at least one test failed.\nif s:fail > 0\n  split /tmp/vim-go-test/FAILED\n  silent write\nendif\n\nlet s:total_elapsed_time = substitute(reltimestr(reltime(s:total_started)), '^\\s*\\(.\\{-}\\)\\s*$', '\\1', '')\n\n\" Also store all internal messages from s:logs as well.\nsilent! split /tmp/vim-go-test/test.tmp\ncall append(line('$'), s:logs)\ncall append(line('$'), printf(\"%s %s %s %ss / %s tests\",\n      \\ (s:fail > 0 ? 'FAIL' : 'ok  '),\n      \\ s:testfile,\n      \\ repeat(' ', 25 - len(s:testfile)),\n      \\ s:total_elapsed_time, s:done))\nif g:test_verbose is 0\n  silent :g/^$/d\nendif\nsilent! write\n\n\" Our work here is done.\nqall!\n\n\" restore Vi compatibility settings\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim:ts=2:sts=2:sw=2:et\n"
  },
  {
    "path": "scripts/test",
    "content": "#!/bin/sh\n#\n# Run all tests.\n#\n\nset -euC\nvimgodir=$(cd -P \"$(dirname \"$0\")/..\" > /dev/null && pwd)\ncd \"$vimgodir\"\n\n_usage() {\n  echo \"Usage: ${0##*/} [-hvc] [-r file] vim_version\"\n  echo\n  echo \"Options:\"\n  echo \"  -h     Show this help\"\n  echo \"  -v     Enable verbose output\"\n  echo \"  -r     Run only the tests from this file\"\n  echo \"  -c     Generate code coverage reports\"\n  echo \"  -u     Submit code coverage reports\"\n  echo\n}\n\nverbose=0\nrun=\"\"\ncoverage=\"\"\nuploadcoverage=\"\"\nwhile getopts \"hvcur:\" option; do\n  case \"$option\" in\n      h) _usage; exit 0 ;;\n      v) verbose=1 ;;\n      r) run=$OPTARG ;;\n      c) coverage=\"-c\" ;;\n      u) uploadcoverage=1 ;;\n      *)\n        echo \"error: unknown option '$option'\"\n        _usage\n        exit 1\n        ;;\n  esac\ndone\nshift $((OPTIND - 1))\n\n### Setup Vim and other dependencies.\n#####################################\nif [ -z \"${1:-}\" ]; then\n  echo \"unknown version: '${1:-}'\"\n  echo \"First argument must be 'vim-8.2', 'vim-9.1', or 'nvim'.\"\n  exit 1\nfi\n\nvim=$1\nvimdir=\"/tmp/vim-go-test/$vim-install\"\nexport GOPATH=$vimdir\nexport PATH=\"${GOPATH}/bin:$PATH\"\n\nif [ ! -f \"$vimdir/bin/vim\" ]; then\n  echo \"$vimdir/bin/vim doesn't exist; did you install it with the install-vim script?\"\n  exit 1\nfi\n\n### Run tests.\n##############\n# Clean stale log file.\n[ -f '/tmp/vim-go-test/test.log' ]        && rm '/tmp/vim-go-test/test.log'\n[ -f '/tmp/vim-go-test/FAILED' ]          && rm '/tmp/vim-go-test/FAILED'\n[ -f '/tmp/vim-go-test/cov-profile.txt' ] && rm '/tmp/vim-go-test/cov-profile.txt'\n[ -f '/tmp/vim-go-test/cov-report.txt' ]  && rm '/tmp/vim-go-test/cov-report.txt'\n\n# Run the actual tests.\nfind \"$vimgodir\" -name '*_test.vim' | sort | while read test_file; do\n  [ -n \"$run\" -a \"$(basename \"$test_file\")\" != \"$run\" ] && continue\n\n  \"$vimgodir/scripts/run-vim\" $coverage $vim -e \\\n    +\"silent e $test_file\" \\\n    +\"let g:test_verbose=$verbose\" \\\n    +\"let g:go_echo_command_info=0\" \\\n    -S ./scripts/runtest.vim < /dev/null || (\n      # If Vim exits with non-0 it's almost certainly a bug in the test runner;\n      # should very rarely happen in normal usage.\n      echo 'test runner failure'\n      cat '/tmp/vim-go-test/test.tmp'\n      rm '/tmp/vim-go-test/test.tmp'\n      exit 5\n    )\n\n  # Append logs\n  cat '/tmp/vim-go-test/test.tmp' | tee '/tmp/vim-go-test/test.log'\n  rm '/tmp/vim-go-test/test.tmp'\ndone\n\necho\nif [ -f \"/tmp/vim-go-test/FAILED\" ]; then\n  echo 2>&1 \"Some ($vim) tests FAILED\"\n  exit 1\nfi\necho 2>&1 \"All ($vim) tests PASSED\"\n\n# Generate coverage reports\nif [ -n \"$coverage\" ]; then\n  coverage xml --omit '*_test.vim'\n\n  if [ -n \"$uploadcoverage\" ]; then\n    codecov -X search gcov pycov -f coverage.xml --required \\\n    --flags \"$(echo \"$vim\" | sed -s 's/[-.]//g')\"\n    rm coverage.xml\n  fi\nfi\n\n# vim:ts=2:sts=2:sw=2:et\n"
  },
  {
    "path": "syntax/go.vim",
    "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\" go.vim: Vim syntax file for Go.\n\n\" Quit when a (custom) syntax file was already loaded\nif exists(\"b:current_syntax\")\n  finish\nendif\n\nsyn case match\n\nsyn keyword     goPackage           package\nsyn keyword     goImport            import    contained\nsyn keyword     goVar               var       contained\nsyn keyword     goConst             const     contained\n\nhi def link     goPackage           Statement\nhi def link     goImport            Statement\nhi def link     goVar               Keyword\nhi def link     goConst             Keyword\nhi def link     goDeclaration       Keyword\n\n\" Keywords within functions\nsyn keyword     goStatement         defer go goto return break continue fallthrough\nsyn keyword     goConditional       if else switch select\nsyn keyword     goLabel             case default\nsyn keyword     goRepeat            for range\n\nhi def link     goStatement         Statement\nhi def link     goConditional       Conditional\nhi def link     goLabel             Label\nhi def link     goRepeat            Repeat\n\n\" Predefined types\nsyn keyword     goType              chan map bool string error any comparable\nsyn keyword     goSignedInts        int int8 int16 int32 int64 rune\nsyn keyword     goUnsignedInts      byte uint uint8 uint16 uint32 uint64 uintptr\nsyn keyword     goFloats            float32 float64\nsyn keyword     goComplexes         complex64 complex128\n\nhi def link     goType              Type\nhi def link     goSignedInts        Type\nhi def link     goUnsignedInts      Type\nhi def link     goFloats            Type\nhi def link     goComplexes         Type\n\n\" Predefined functions and values\nsyn keyword     goBuiltins                 append cap clear close complex copy delete imag len\nsyn keyword     goBuiltins                 make max min new panic print println real recover\nsyn keyword     goBoolean                  true false\nsyn keyword     goPredefinedIdentifiers    nil iota\n\nhi def link     goBuiltins                 Identifier\nhi def link     goPredefinedIdentifiers    Constant\n\" Boolean links to Constant by default by vim: goBoolean and goPredefinedIdentifiers\n\" will be highlighted the same, but having the separate allows users to have\n\" separate highlighting for them if they desire.\nhi def link     goBoolean                  Boolean\n\n\" Comments; their contents\nsyn keyword     goTodo              contained TODO FIXME XXX BUG\nsyn cluster     goCommentGroup      contains=goTodo\n\nsyn region      goComment           start=\"//\" end=\"$\" contains=goGenerate,@goCommentGroup,@Spell\nif go#config#FoldEnable('comment')\n  syn region    goComment           start=\"/\\*\" end=\"\\*/\" contains=@goCommentGroup,@Spell fold\n  syn match     goComment           \"\\v(^\\s*//.*\\n)+\" contains=goGenerate,@goCommentGroup,@Spell fold\nelse\n  syn region    goComment           start=\"/\\*\" end=\"\\*/\" contains=@goCommentGroup,@Spell\nendif\n\nhi def link     goComment           Comment\nhi def link     goTodo              Todo\n\nif go#config#HighlightGenerateTags()\n  syn match       goGenerateVariables contained /\\%(\\$GOARCH\\|\\$GOOS\\|\\$GOFILE\\|\\$GOLINE\\|\\$GOPACKAGE\\|\\$DOLLAR\\)\\>/\n  syn region      goGenerate          start=\"^\\s*//go:generate\" end=\"$\" contains=goGenerateVariables\n  hi def link     goGenerate          PreProc\n  hi def link     goGenerateVariables Special\nendif\n\n\" Go escapes\nsyn match       goEscapeOctal       display contained \"\\\\[0-7]\\{3}\"\nsyn match       goEscapeC           display contained +\\\\[abfnrtv\\\\'\"]+\nsyn match       goEscapeX           display contained \"\\\\x\\x\\{2}\"\nsyn match       goEscapeU           display contained \"\\\\u\\x\\{4}\"\nsyn match       goEscapeBigU        display contained \"\\\\U\\x\\{8}\"\nsyn match       goEscapeError       display contained +\\\\[^0-7xuUabfnrtv\\\\'\"]+\n\nhi def link     goEscapeOctal       goSpecialString\nhi def link     goEscapeC           goSpecialString\nhi def link     goEscapeX           goSpecialString\nhi def link     goEscapeU           goSpecialString\nhi def link     goEscapeBigU        goSpecialString\nhi def link     goSpecialString     Special\nhi def link     goEscapeError       Error\n\n\" Strings and their contents\nsyn cluster     goStringGroup       contains=goEscapeOctal,goEscapeC,goEscapeX,goEscapeU,goEscapeBigU,goEscapeError\nif go#config#HighlightStringSpellcheck()\n  syn region      goString            start=+\"+ skip=+\\\\\\\\\\|\\\\\"+ end=+\"+ contains=@goStringGroup,@Spell\n  syn region      goRawString         start=+`+ end=+`+ contains=@Spell\nelse\n  syn region      goString            start=+\"+ skip=+\\\\\\\\\\|\\\\\"+ end=+\"+ contains=@goStringGroup\n  syn region      goRawString         start=+`+ end=+`+\nendif\n\nsyn match       goImportString      /^\\%(\\s\\+\\|import \\)\\(\\h\\w* \\)\\?\\zs\"[^\"]\\+\"/ contained containedin=goImport\n\nif go#config#HighlightFormatStrings()\n  \" [n] notation is valid for specifying explicit argument indexes\n  \" 1. Match a literal % not preceded by a %.\n  \" 2. Match any number of -, #, 0, space, or +\n  \" 3. Match * or [n]* or any number or nothing before a .\n  \" 4. Match * or [n]* or any number or nothing after a .\n  \" 5. Match [n] or nothing before a verb\n  \" 6. Match a formatting verb\n  syn match       goFormatSpecifier   /\\\n        \\%([^%]\\%(%%\\)*\\)\\\n        \\@<=%[-#0 +]*\\\n        \\%(\\%(\\%(\\[\\d\\+\\]\\)\\=\\*\\)\\|\\d\\+\\)\\=\\\n        \\%(\\.\\%(\\%(\\%(\\[\\d\\+\\]\\)\\=\\*\\)\\|\\d\\+\\)\\=\\)\\=\\\n        \\%(\\[\\d\\+\\]\\)\\=[vTtbcdoqxXUeEfFgGspw]/ contained containedin=goString,goRawString\n  hi def link     goFormatSpecifier   goSpecialString\nendif\n\nhi def link     goImportString      String\nhi def link     goString            String\nhi def link     goRawString         String\n\n\" Characters; their contents\nsyn cluster     goCharacterGroup    contains=goEscapeOctal,goEscapeC,goEscapeX,goEscapeU,goEscapeBigU\nsyn region      goCharacter         start=+'+ skip=+\\\\\\\\\\|\\\\'+ end=+'+ contains=@goCharacterGroup\n\nhi def link     goCharacter         Character\n\n\" Regions\nsyn region      goParen             start='(' end=')' transparent\nif go#config#FoldEnable('block')\n  syn region    goBlock             start=\"{\" end=\"}\" transparent fold\nelse\n  syn region    goBlock             start=\"{\" end=\"}\" transparent\nendif\n\n\" import\nif go#config#FoldEnable('import')\n  syn region    goImport            start='import (' end=')' transparent fold contains=goImport,goImportString,goComment\n  syn match     goImport            /^import ()/ transparent fold contains=goImport\nelse\n  syn region    goImport            start='import (' end=')' transparent contains=goImport,goImportString,goComment\n  syn match     goImport            /^import ()/ transparent contains=goImport\nendif\n\n\" var, const\nif go#config#FoldEnable('varconst')\n  syn region    goVar               start='var ('   end='^\\s*)$' transparent fold\n                                  \\ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator\n  syn match     goVar               /var ()/ transparent fold\n                                  \\ contains=goVar\n  syn region    goConst             start='const (' end='^\\s*)$' transparent fold\n                                  \\ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator\n  syn match     goConst             /const ()/ transparent fold\n                                  \\ contains=goConst\nelse\n  syn region    goVar               start='var ('   end='^\\s*)$' transparent\n                                  \\ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator\n  syn match     goVar               /var ()/ transparent\n                                  \\ contains=goVar\n  syn region    goConst             start='const (' end='^\\s*)$' transparent\n                                  \\ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator\n  syn match     goConst             /const ()/ transparent\n                                  \\ contains=goConst\nendif\n\n\" Single-line var, const, and import.\nsyn match       goSingleDecl        /\\%(import\\|var\\|const\\) [^(]\\@=/ contains=goImport,goVar,goConst\n\n\" Integers\nsyn match       goDecimalInt        \"\\<-\\=\\%(0\\|\\%(\\d\\|\\d_\\d\\)\\+\\)\\>\"\nsyn match       goHexadecimalInt    \"\\<-\\=0[xX]_\\?\\%(\\x\\|\\x_\\x\\)\\+\\>\"\nsyn match       goOctalInt          \"\\<-\\=0[oO]\\?_\\?\\%(\\o\\|\\o_\\o\\)\\+\\>\"\nsyn match       goBinaryInt         \"\\<-\\=0[bB]_\\?\\%([01]\\|[01]_[01]\\)\\+\\>\"\n\nhi def link     goDecimalInt        Integer\nhi def link     goDecimalError      Error\nhi def link     goHexadecimalInt    Integer\nhi def link     goHexadecimalError  Error\nhi def link     goOctalInt          Integer\nhi def link     goOctalError        Error\nhi def link     goBinaryInt         Integer\nhi def link     goBinaryError       Error\nhi def link     Integer             Number\n\n\" Floating point\n\"float_lit         = decimal_float_lit | hex_float_lit .\n\"\n\"decimal_float_lit = decimal_digits \".\" [ decimal_digits ] [ decimal_exponent ] |\n\"                    decimal_digits decimal_exponent |\n\"                    \".\" decimal_digits [ decimal_exponent ] .\n\"decimal_exponent  = ( \"e\" | \"E\" ) [ \"+\" | \"-\" ] decimal_digits .\n\"\n\"hex_float_lit     = \"0\" ( \"x\" | \"X\" ) hex_mantissa hex_exponent .\n\"hex_mantissa      = [ \"_\" ] hex_digits \".\" [ hex_digits ] |\n\"                    [ \"_\" ] hex_digits |\n\"                    \".\" hex_digits .\n\"hex_exponent      = ( \"p\" | \"P\" ) [ \"+\" | \"-\" ] decimal_digits .\n\" decimal floats with a decimal point\nsyn match       goFloat             \"\\<-\\=\\%(0\\|\\%(\\d\\|\\d_\\d\\)\\+\\)\\.\\%(\\%(\\%(\\d\\|\\d_\\d\\)\\+\\)\\=\\%([Ee][-+]\\=\\%(\\d\\|\\d_\\d\\)\\+\\)\\=\\>\\)\\=\"\nsyn match       goFloat             \"\\s\\zs-\\=\\.\\%(\\d\\|\\d_\\d\\)\\+\\%(\\%([Ee][-+]\\=\\%(\\d\\|\\d_\\d\\)\\+\\)\\>\\)\\=\"\n\" decimal floats without a decimal point\nsyn match       goFloat             \"\\<-\\=\\%(0\\|\\%(\\d\\|\\d_\\d\\)\\+\\)[Ee][-+]\\=\\%(\\d\\|\\d_\\d\\)\\+\\>\"\n\" hexadecimal floats with a decimal point\nsyn match       goHexadecimalFloat  \"\\<-\\=0[xX]\\%(_\\x\\|\\x\\)\\+\\.\\%(\\%(\\x\\|\\x_\\x\\)\\+\\)\\=\\%([Pp][-+]\\=\\%(\\d\\|\\d_\\d\\)\\+\\)\\=\\>\"\nsyn match       goHexadecimalFloat  \"\\<-\\=0[xX]\\.\\%(\\x\\|\\x_\\x\\)\\+\\%([Pp][-+]\\=\\%(\\d\\|\\d_\\d\\)\\+\\)\\=\\>\"\n\" hexadecimal floats without a decimal point\nsyn match       goHexadecimalFloat  \"\\<-\\=0[xX]\\%(_\\x\\|\\x\\)\\+[Pp][-+]\\=\\%(\\d\\|\\d_\\d\\)\\+\\>\"\n\nhi def link     goFloat             Float\nhi def link     goHexadecimalFloat  Float\n\n\" Imaginary literals\nsyn match       goImaginaryDecimal        \"\\<-\\=\\%(0\\|\\%(\\d\\|\\d_\\d\\)\\+\\)i\\>\"\nsyn match       goImaginaryHexadecimal    \"\\<-\\=0[xX]_\\?\\%(\\x\\|\\x_\\x\\)\\+i\\>\"\nsyn match       goImaginaryOctal          \"\\<-\\=0[oO]\\?_\\?\\%(\\o\\|\\o_\\o\\)\\+i\\>\"\nsyn match       goImaginaryBinary         \"\\<-\\=0[bB]_\\?\\%([01]\\|[01]_[01]\\)\\+i\\>\"\n\n\" imaginary decimal floats with a decimal point\nsyn match       goImaginaryFloat             \"\\<-\\=\\%(0\\|\\%(\\d\\|\\d_\\d\\)\\+\\)\\.\\%(\\%(\\%(\\d\\|\\d_\\d\\)\\+\\)\\=\\%([Ee][-+]\\=\\%(\\d\\|\\d_\\d\\)\\+\\)\\=\\)\\=i\\>\"\nsyn match       goImaginaryFloat             \"\\s\\zs-\\=\\.\\%(\\d\\|\\d_\\d\\)\\+\\%([Ee][-+]\\=\\%(\\d\\|\\d_\\d\\)\\+\\)\\=i\\>\"\n\" imaginary decimal floats without a decimal point\nsyn match       goImaginaryFloat             \"\\<-\\=\\%(0\\|\\%(\\d\\|\\d_\\d\\)\\+\\)[Ee][-+]\\=\\%(\\d\\|\\d_\\d\\)\\+i\\>\"\n\" imaginary hexadecimal floats with a decimal point\nsyn match       goImaginaryHexadecimalFloat  \"\\<-\\=0[xX]\\%(_\\x\\|\\x\\)\\+\\.\\%(\\%(\\x\\|\\x_\\x\\)\\+\\)\\=\\%([Pp][-+]\\=\\%(\\d\\|\\d_\\d\\)\\+\\)\\=i\\>\"\nsyn match       goImaginaryHexadecimalFloat  \"\\<-\\=0[xX]\\.\\%(\\x\\|\\x_\\x\\)\\+\\%([Pp][-+]\\=\\%(\\d\\|\\d_\\d\\)\\+\\)\\=i\\>\"\n\" imaginary hexadecimal floats without a decimal point\nsyn match       goImaginaryHexadecimalFloat  \"\\<-\\=0[xX]\\%(_\\x\\|\\x\\)\\+[Pp][-+]\\=\\%(\\d\\|\\d_\\d\\)\\+i\\>\"\n\nhi def link     goImaginaryDecimal             Number\nhi def link     goImaginaryHexadecimal         Number\nhi def link     goImaginaryOctal               Number\nhi def link     goImaginaryBinary              Number\nhi def link     goImaginaryFloat               Float\nhi def link     goImaginaryHexadecimalFloat    Float\n\n\" Spaces after \"[]\"\nif go#config#HighlightArrayWhitespaceError()\n  syn match goSpaceError display \"\\%(\\[\\]\\)\\@<=\\s\\+\"\nendif\n\n\" Spacing errors around the 'chan' keyword\nif go#config#HighlightChanWhitespaceError()\n  \" receive-only annotation on chan type\n  \"\n  \" \\(\\<chan\\>\\)\\@<!<-  (only pick arrow when it doesn't come after a chan)\n  \" this prevents picking up 'chan<- chan<-' but not '<- chan'\n  syn match goSpaceError display \"\\%(\\%(\\<chan\\>\\)\\@<!<-\\)\\@<=\\s\\+\\%(\\<chan\\>\\)\\@=\"\n\n  \" send-only annotation on chan type\n  \"\n  \" \\(<-\\)\\@<!\\<chan\\>  (only pick chan when it doesn't come after an arrow)\n  \" this prevents picking up '<-chan <-chan' but not 'chan <-'\n  syn match goSpaceError display \"\\%(\\%(<-\\)\\@<!\\<chan\\>\\)\\@<=\\s\\+\\%(<-\\)\\@=\"\n\n  \" value-ignoring receives in a few contexts\n  syn match goSpaceError display \"\\%(\\%(^\\|[={(,;]\\)\\s*<-\\)\\@<=\\s\\+\"\nendif\n\n\" Extra types commonly seen\nif go#config#HighlightExtraTypes()\n  syn match goExtraType /\\<bytes\\.\\%(Buffer\\)\\>/\n  syn match goExtraType /\\<context\\.\\%(Context\\)\\>/\n  syn match goExtraType /\\<io\\.\\%(Reader\\|ReadSeeker\\|ReadWriter\\|ReadCloser\\|ReadWriteCloser\\|Writer\\|WriteCloser\\|Seeker\\)\\>/\n  syn match goExtraType /\\<reflect\\.\\%(Kind\\|Type\\|Value\\)\\>/\n  syn match goExtraType /\\<unsafe\\.Pointer\\>/\nendif\n\n\" Space-tab error\nif go#config#HighlightSpaceTabError()\n  syn match goSpaceError display \" \\+\\t\"me=e-1\nendif\n\n\" Trailing white space error\nif go#config#HighlightTrailingWhitespaceError()\n  syn match goSpaceError display excludenl \"\\s\\+$\"\nendif\n\nhi def link     goExtraType         Type\nhi def link     goSpaceError        Error\n\n\n\n\" included from: https://github.com/athom/more-colorful.vim/blob/master/after/syntax/go.vim\n\"\n\" Comments; their contents\nsyn keyword     goTodo              contained NOTE\nhi def link     goTodo              Todo\n\nsyn match goVarArgs /\\.\\.\\./\n\n\" Operators;\nif go#config#HighlightOperators()\n  \" match single-char operators:          - + % < > ! & | ^ * =\n  \" and corresponding two-char operators: -= += %= <= >= != &= |= ^= *= ==\n  syn match goOperator /[-+%<>!&|^*=]=\\?/\n  \" match / and /=\n  syn match goOperator /\\/\\%(=\\|\\ze[^/*]\\)/\n  \" match two-char operators:               << >> &^\n  \" and corresponding three-char operators: <<= >>= &^=\n  syn match goOperator /\\%(<<\\|>>\\|&^\\)=\\?/\n  \" match remaining two-char operators: := && || <- ++ --\n  syn match goOperator /:=\\|||\\|<-\\|++\\|--/\n  \" match ~\n  syn match goOperator /\\~/\n  \" match ...\n\n  hi def link     goPointerOperator   goOperator\n  hi def link     goVarArgs           goOperator\nendif\nhi def link     goOperator          Operator\n\n\"                               -> type constraint opening bracket\n\"                               |-> start non-counting group\n\"                               ||  -> any word character\n\"                               ||  |  -> at least one, as many as possible\n\"                               ||  |  |    -> start non-counting group\n\"                               ||  |  |    |   -> match ~\n\"                               ||  |  |    |   | -> at most once\n\"                               ||  |  |    |   | |     -> allow a slice type\n\"                               ||  |  |    |   | |     |      -> any word character\n\"                               ||  |  |    |   | |     |      | -> start a non-counting group\n\"                               ||  |  |    |   | |     |      | | -> that matches word characters and |\n\"                               ||  |  |    |   | |     |      | | |     -> close the non-counting group\n\"                               ||  |  |    |   | |     |      | | |     | -> close the non-counting group\n\"                               ||  |  |    |   | |     |      | | |     | |-> any number of matches\n\"                               ||  |  |    |   | |     |      | | |     | || -> start a non-counting group\n\"                               ||  |  |    |   | |     |      | | |     | || | -> a comma and whitespace\n\"                               ||  |  |    |   | |     |      | | |     | || | |      -> at most once\n\"                               ||  |  |    |   | |     |      | | |     | || | |      | -> close the non-counting group\n\"                               ||  |  |    |   | |     |      | | |     | || | |      | | -> at least one of those non-counting groups, as many as possible\n\"                               ||  |  |    |   | | --------   | | |     | || | |      | | | -> type constraint closing bracket\n\"                               ||  |  |    |   | ||        |  | | |     | || | |      | | | |\nsyn match goTypeParams        /\\[\\%(\\w\\+\\s\\+\\%(\\~\\?\\%(\\[]\\)\\?\\w\\%(\\w\\||\\)\\)*\\%(,\\s*\\)\\?\\)\\+\\]/ nextgroup=goSimpleParams,goDeclType contained\n\n\" Functions;\nif go#config#HighlightFunctions() || go#config#HighlightFunctionParameters()\n  syn match goDeclaration       /\\<func\\>/ nextgroup=goReceiver,goFunction,goSimpleParams skipwhite skipnl\n  syn match goReceiverDecl      /(\\s*\\zs\\%(\\%(\\w\\+\\s\\+\\)\\?\\*\\?\\w\\+\\%(\\[\\%(\\%(\\[\\]\\)\\?\\w\\+\\%(,\\s*\\)\\?\\)\\+\\]\\)\\?\\)\\ze\\s*)/ contained contains=goReceiverVar,goReceiverType,goPointerOperator\n  syn match goReceiverVar       /\\w\\+\\ze\\s\\+\\%(\\w\\|\\*\\)/ nextgroup=goPointerOperator,goReceiverType skipwhite skipnl contained\n  syn match goPointerOperator   /\\*/ nextgroup=goReceiverType contained skipwhite skipnl\n  syn match goFunction          /\\w\\+/ nextgroup=goSimpleParams,goTypeParams contained skipwhite skipnl\n  syn match goReceiverType      /\\w\\+\\%(\\[\\%(\\%(\\[\\]\\)\\?\\w\\+\\%(,\\s*\\)\\?\\)\\+\\]\\)\\?\\ze\\s*)/ contained\n  if go#config#HighlightFunctionParameters()\n    syn match goSimpleParams      /(\\%(\\w\\|\\_s\\|[*\\.\\[\\],\\{\\}<>-]\\)*)/ contained contains=goParamName,goType nextgroup=goFunctionReturn skipwhite skipnl\n    syn match goFunctionReturn   /(\\%(\\w\\|\\_s\\|[*\\.\\[\\],\\{\\}<>-]\\)*)/ contained contains=goParamName,goType skipwhite skipnl\n    syn match goParamName        /\\w\\+\\%(\\s*,\\s*\\w\\+\\)*\\ze\\s\\+\\%(\\w\\|\\.\\|\\*\\|\\[\\)/ contained nextgroup=goParamType skipwhite skipnl\n    syn match goParamType        /\\%([^,)]\\|\\_s\\)\\+,\\?/ contained nextgroup=goParamName skipwhite skipnl\n                          \\ contains=goVarArgs,goType,goSignedInts,goUnsignedInts,goFloats,goComplexes,goDeclType,goBlock\n    hi def link   goReceiverVar    goParamName\n    hi def link   goParamName      Identifier\n  endif\n  syn match goReceiver          /(\\s*\\%(\\w\\+\\s\\+\\)\\?\\*\\?\\s*\\w\\+\\%(\\[\\%(\\%(\\[\\]\\)\\?\\w\\+\\%(,\\s*\\)\\?\\)\\+\\]\\)\\?\\s*)\\ze\\s*\\w/ contained nextgroup=goFunction contains=goReceiverDecl skipwhite skipnl\nelse\n  syn keyword goDeclaration func\nendif\nhi def link     goFunction          Function\n\n\" Function calls;\nif go#config#HighlightFunctionCalls()\n  syn match goFunctionCall      /\\w\\+\\ze\\%(\\[\\%(\\%(\\[]\\)\\?\\w\\+\\(,\\s*\\)\\?\\)\\+\\]\\)\\?(/ contains=goBuiltins,goDeclaration\nendif\nhi def link     goFunctionCall      Type\n\n\" Fields;\nif go#config#HighlightFields()\n  \" 1. Match a sequence of word characters coming after a '.'\n  \" 2. Require the following but dont match it: ( \\@= see :h E59)\n  \"    - The symbols: / - + * %   OR\n  \"    - The symbols: [] {} <> )  OR\n  \"    - The symbols: \\n \\r space OR\n  \"    - The symbols: , : .\n  \" 3. Have the start of highlight (hs) be the start of matched\n  \"    pattern (s) offsetted one to the right (+1) (see :h E401)\n  syn match       goField   /\\.\\w\\+\\\n        \\%(\\%([\\/\\-\\+*%]\\)\\|\\\n        \\%([\\[\\]{}<\\>\\)]\\)\\|\\\n        \\%([\\!=\\^|&]\\)\\|\\\n        \\%([\\n\\r\\ ]\\)\\|\\\n        \\%([,\\:.]\\)\\)\\@=/hs=s+1\nendif\nhi def link    goField              Identifier\n\n\" Structs & Interfaces;\nif go#config#HighlightTypes()\n  syn match goTypeConstructor      /\\<\\w\\+{\\@=/\n  syn match goTypeDecl             /\\<type\\>/ nextgroup=goTypeName skipwhite skipnl\n  syn match goTypeName             /\\w\\+/ contained nextgroup=goDeclType,goTypeParams skipwhite skipnl\n  syn match goDeclType             /\\<\\%(interface\\|struct\\)\\>/ skipwhite skipnl\n  hi def link     goReceiverType      Type\nelse\n  syn keyword goDeclType           struct interface\n  syn keyword goDeclaration        type\nendif\nhi def link     goTypeConstructor   Type\nhi def link     goTypeName          Type\nhi def link     goTypeDecl          Keyword\nhi def link     goDeclType          Keyword\n\n\" Variable Assignments\nif go#config#HighlightVariableAssignments()\n  syn match goVarAssign /\\v[_.[:alnum:]]+(,\\s*[_.[:alnum:]]+)*\\ze(\\s*([-^+|^\\/%&]|\\*|\\<\\<|\\>\\>|\\&\\^)?\\=[^=])/\n  hi def link   goVarAssign         Special\nendif\n\n\" Variable Declarations\nif go#config#HighlightVariableDeclarations()\n  syn match goVarDefs /\\v\\w+(,\\s*\\w+)*\\ze(\\s*:\\=)/\n  hi def link   goVarDefs           Special\nendif\n\n\" Build Constraints\nif go#config#HighlightBuildConstraints()\n  syn match   goBuildKeyword      display contained \"+build\\|go:build\"\n  \" Highlight the known values of GOOS, GOARCH, and other +build options.\n  syn keyword goBuildDirectives   contained\n        \\ android darwin dragonfly freebsd linux nacl netbsd openbsd plan9\n        \\ solaris windows 386 amd64 amd64p32 arm armbe arm64 arm64be ppc64\n        \\ ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc\n        \\ s390 s390x sparc sparc64 cgo ignore race\n\n  \" Other words in the build directive are build tags not listed above, so\n  \" avoid highlighting them as comments by using a matchgroup just for the\n  \" start of the comment.\n  \" The rs=s+2 option lets the \\s*+build portion be part of the inner region\n  \" instead of the matchgroup so it will be highlighted as a goBuildKeyword.\n  syn region  goBuildComment      matchgroup=goBuildCommentStart\n        \\ start=\"//\\(\\s*+build\\s\\|go:build\\)\"rs=s+2 end=\"$\"\n        \\ contains=goBuildKeyword,goBuildDirectives\n  hi def link goBuildCommentStart Comment\n  hi def link goBuildDirectives   Type\n  hi def link goBuildKeyword      PreProc\nendif\n\nif go#config#HighlightBuildConstraints() || go#config#FoldEnable('package_comment')\n  \" One or more line comments that are followed immediately by a \"package\"\n  \" declaration are treated like package documentation, so these must be\n  \" matched as comments to avoid looking like working build constraints.\n  \" The he, me, and re options let the \"package\" itself be highlighted by\n  \" the usual rules.\n  exe 'syn region  goPackageComment    start=/\\v(\\/\\/.*\\n)+\\s*package\\s/'\n        \\ . ' end=/\\v\\n\\s*package\\s/he=e-8,me=e-8,re=e-8'\n        \\ . ' contains=@goCommentGroup,@Spell'\n        \\ . (go#config#FoldEnable('package_comment') ? ' fold' : '')\n  exe 'syn region  goPackageComment    start=/\\v^\\s*\\/\\*.*\\n(.*\\n)*\\s*\\*\\/\\npackage\\s/'\n        \\ . ' end=/\\v\\*\\/\\n\\s*package\\s/he=e-8,me=e-8,re=e-8'\n        \\ . ' contains=@goCommentGroup,@Spell'\n        \\ . (go#config#FoldEnable('package_comment') ? ' fold' : '')\n  hi def link goPackageComment    Comment\nendif\n\n\" :GoCoverage commands\nhi def link goCoverageNormalText Comment\n\nfunction! s:hi()\n  hi def link goSameId Search\n  hi def link goDiagnosticError SpellBad\n  hi def link goDiagnosticWarning SpellRare\n\n  \" TODO(bc): is it appropriate to define text properties in a syntax file?\n  \" The highlight groups need to be defined before the text properties types\n  \" are added, and when users have syntax enabled in their vimrc after\n  \" filetype plugin on, the highlight groups won't be defined when\n  \" ftplugin/go.vim is executed when the first go file is opened.\n  \" See https://github.com/fatih/vim-go/issues/2658.\n  if has('textprop')\n    if empty(prop_type_get('goSameId'))\n      call prop_type_add('goSameId', {'highlight': 'goSameId'})\n    endif\n    if empty(prop_type_get('goDiagnosticError'))\n      call prop_type_add('goDiagnosticError', {'highlight': 'goDiagnosticError'})\n    endif\n    if empty(prop_type_get('goDiagnosticWarning'))\n      call prop_type_add('goDiagnosticWarning', {'highlight': 'goDiagnosticWarning'})\n    endif\n  endif\n\n  hi def link goDeclsFzfKeyword        Keyword\n  hi def link goDeclsFzfFunction       Function\n  hi def link goDeclsFzfSpecialComment SpecialComment\n  hi def link goDeclsFzfComment        Comment\n\n  \" :GoCoverage commands\n  hi def      goCoverageCovered    ctermfg=green guifg=#A6E22E\n  hi def      goCoverageUncover    ctermfg=red guifg=#F92672\n\n  \" :GoDebug commands\n  if go#config#HighlightDebug()\n    hi def GoDebugBreakpoint term=standout ctermbg=117 ctermfg=0 guibg=#BAD4F5  guifg=Black\n    hi def GoDebugCurrent term=reverse  ctermbg=12  ctermfg=7 guibg=DarkBlue guifg=White\n  endif\nendfunction\n\naugroup vim-go-hi\n  autocmd!\n  autocmd ColorScheme * call s:hi()\naugroup end\ncall s:hi()\n\n\" Search backwards for a global declaration to start processing the syntax.\n\"syn sync match goSync grouphere NONE /^\\(const\\|var\\|type\\|func\\)\\>/\n\n\" There's a bug in the implementation of grouphere. For now, use the\n\" following as a more expensive/less precise workaround.\nsyn sync minlines=500\n\nlet b:current_syntax = \"go\"\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "syntax/godebugoutput.vim",
    "content": "if exists(\"b:current_syntax\")\n  finish\nendif\n\nsyn match godebugOutputErr '^ERR:.*'\nsyn match godebugOutputOut '^OUT:.*'\n\nlet b:current_syntax = \"godebugoutput\"\n\nhi def link godebugOutputErr Comment\nhi def link godebugOutputOut Normal\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "syntax/godebugstacktrace.vim",
    "content": "if exists(\"b:current_syntax\")\n  finish\nendif\n\nsyn match godebugStacktrace '^\\S\\+'\n\nlet b:current_syntax = \"godebugoutput\"\n\nhi def link godebugStacktrace Function\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "syntax/godebugvariables.vim",
    "content": "if exists(\"b:current_syntax\")\n  finish\nendif\n\nsyn match godebugTitle '^#.*'\nsyn match godebugVariables '^\\s*\\S\\+\\ze:'\n\nsyn keyword     goType              chan map bool string error\nsyn keyword     goSignedInts        int int8 int16 int32 int64 rune\nsyn keyword     goUnsignedInts      byte uint uint8 uint16 uint32 uint64 uintptr\nsyn keyword     goFloats            float32 float64\nsyn keyword     goComplexes         complex64 complex128\n\nsyn keyword     goBoolean                  true false\n\nlet b:current_syntax = \"godebugvariables\"\n\nhi def link godebugTitle Underlined\nhi def link godebugVariables Statement\nhi def link goType Type\nhi def link goBoolean Boolean\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "syntax/godefstack.vim",
    "content": "if exists(\"b:current_syntax\")\n  finish\nendif\n\nsyn match godefStackComment             '^\".*'\nsyn match godefLinePrefix               '^[>\\s]\\s' nextgroup=godefStackEntryNumber contains=godefStackCurrentPosition\nsyn match godefStackEntryNumber         '\\d\\+' nextgroup=godefStackFilename skipwhite\nsyn match godefStackCurrentPosition     '>' contained\nsyn match godefStackFilename            '[^|]\\+' contained nextgroup=godefStackEntryLocation\nsyn region godefStackEntryLocation      oneline start='|' end='|' contained contains=godefStackEntryLocationNumber\nsyn match godefStackEntryLocationNumber '\\d\\+' contained display\n\nlet b:current_syntax = \"godefstack\"\n\nhi def link godefStackComment           Comment\nhi def link godefStackCurrentPosition   Special\nhi def link godefStackFilename          Directory\nhi def link godefStackEntryLocationNumber LineNr\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "syntax/gohtmltmpl.vim",
    "content": "if exists(\"b:current_syntax\")\n  finish\nendif\n\nif !exists(\"g:main_syntax\")\n  let g:main_syntax = 'html'\nendif\n\nruntime! syntax/gotexttmpl.vim\nruntime! syntax/html.vim\nunlet b:current_syntax\n\nsyn cluster htmlPreproc add=gotplAction,goTplComment\n\nlet b:current_syntax = \"gohtmltmpl\"\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "syntax/gomod.vim",
    "content": "\" gomod.vim: Vim syntax file for go.mod file\n\"\n\" Quit when a (custom) syntax file was already loaded\nif exists(\"b:current_syntax\")\n  finish\nendif\n\nsyntax case match\n\n\" Reference documentation:\n\" https://golang.org/ref/mod#go-mod-file-grammar\n\n\" match keywords\nsyntax keyword gomodModule     module\nsyntax keyword gomodGo         go        contained\nsyntax keyword gomodToolchain  toolchain contained\nsyntax keyword gomodRequire    require\nsyntax keyword gomodExclude    exclude\nsyntax keyword gomodReplace    replace\nsyntax keyword gomodRetract    retract\n\n\" require, exclude, replace, and go can be also grouped into block\nsyntax region gomodRequire start='require (' end=')' transparent contains=gomodRequire,gomodVersion\nsyntax region gomodExclude start='exclude (' end=')' transparent contains=gomodExclude,gomodVersion\nsyntax region gomodReplace start='replace (' end=')' transparent contains=gomodReplace,gomodVersion\nsyntax region gomodRetract start='retract (' end=')' transparent contains=gomodVersionRange,gomodVersion\nsyntax match  gomodGo            '^go .*$'           transparent contains=gomodGo,gomodGoVersion\nsyntax match  gomodToolchain     '^toolchain .*$'    transparent contains=gomodToolchain,gomodToolchainVersion\n\n\" set highlights\nhighlight default link gomodModule     Keyword\nhighlight default link gomodGo         Keyword\nhighlight default link gomodToolchain  Keyword\nhighlight default link gomodRequire    Keyword\nhighlight default link gomodExclude    Keyword\nhighlight default link gomodReplace    Keyword\nhighlight default link gomodRetract    Keyword\n\n\" comments are always in form of // ...\nsyntax region gomodComment  start=\"//\" end=\"$\" contains=@Spell\nhighlight default link gomodComment Comment\n\n\" make sure quoted import paths are higlighted\nsyntax region gomodString start=+\"+ skip=+\\\\\\\\\\|\\\\\"+ end=+\"+ \nhighlight default link gomodString  String \n\n\" replace operator is in the form of '=>'\nsyntax match gomodReplaceOperator \"\\v\\=\\>\"\nhighlight default link gomodReplaceOperator Operator\n\n\" match toolchain versions, based on https://go.dev/doc/toolchain#version,\n\"  * default\n\"  * go1\n\"  * go1.X.Y\n\"  * go1.X\n\"  * go1.XrcN\n\"  * go1.XrcN-somesuffix\n\"  * go1.X.Y-somesuffix\nsyntax match gomodToolchainVersion \"default$\" contained\nsyntax match gomodToolchainVersion \"go1\\(.\\d\\+\\)\\{,2\\}\\(rc\\d\\+\\)\\?\\([ \\t-].*\\)\\?\" contained\nhighlight default link gomodToolchainVersion Identifier\n\n\" match go versions\nsyntax match gomodGoVersion \"\\(1.\\d\\+\\)\\(\\(.\\d\\+\\)\\|\\(rc\\d\\+\\)\\)\\?\" contained\nhighlight default link gomodGoVersion Identifier\n\n\" highlight versions:\n\"  * vX.Y.Z-pre\n\"  * vX.Y.Z\n\"  * vX.0.0-yyyyymmddhhmmss-abcdefabcdef\n\"  * vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef\n\"  * vX.Y.(Z+1)-0.yyyymmddhhss-abcdefabcdef\n\"  see https://godoc.org/golang.org/x/tools/internal/semver for more\n\"  information about how semantic versions are parsed and\n\"  https://golang.org/cmd/go/ for how pseudo-versions and +incompatible\n\"  are applied.\n\n\n\" match vX.Y.Z and their prereleases\nsyntax match gomodVersion \"v\\d\\+\\.\\d\\+\\.\\d\\+\\%(-\\%([0-9A-Za-z-]\\+\\)\\%(\\.[0-9A-Za-z-]\\+\\)*\\)\\?\\%(+\\%([0-9A-Za-z-]\\+\\)\\(\\.[0-9A-Za-z-]\\+\\)*\\)\\?\"\n\"                          ^--- version ---^^------------ pre-release  ---------------------^^--------------- metadata ---------------------^\n\"   \t                     ^--------------------------------------- semantic version -------------------------------------------------------^\n\n\" match pseudo versions\n\" without a major version before the commit (e.g.  vX.0.0-yyyymmddhhmmss-abcdefabcdef)\nsyntax match gomodVersion  \"v\\d\\+\\.0\\.0-\\d\\{14\\}-\\x\\+\"\n\" when most recent version before target is a pre-release\nsyntax match gomodVersion  \"v\\d\\+\\.\\d\\+\\.\\d\\+-\\%([0-9A-Za-z-]\\+\\)\\%(\\.[0-9A-Za-z-]\\+\\)*\\%(+\\%([0-9A-Za-z-]\\+\\)\\(\\.[0-9A-Za-z-]\\+\\)*\\)\\?\\.0\\.\\d\\{14}-\\x\\+\"\n\"                          ^--- version ---^^--- ------ pre-release -----------------^^--------------- metadata ---------------------^\n\"                     \t   ^------------------------------------- semantic version --------------------------------------------------^\n\" most recent version before the target is X.Y.Z\nsyntax match gomodVersion \"v\\d\\+\\.\\d\\+\\.\\d\\+\\%(+\\%([0-9A-Za-z-]\\+\\)\\(\\.[0-9A-Za-z-]\\+\\)*\\)\\?-0\\.\\d\\{14}-\\x\\+\"\n\"                          ^--- version ---^^--------------- metadata ---------------------^\n\n\" match incompatible vX.Y.Z and their prereleases\nsyntax match gomodVersion \"v[2-9]\\{1}\\d*\\.\\d\\+\\.\\d\\+\\%(-\\%([0-9A-Za-z-]\\+\\)\\%(\\.[0-9A-Za-z-]\\+\\)*\\)\\?\\%(+\\%([0-9A-Za-z-]\\+\\)\\(\\.[0-9A-Za-z-]\\+\\)*\\)\\?+incompatible\"\n\"                          ^------- version -------^^------------- pre-release ---------------------^^--------------- metadata ---------------------^\n\"               \t         ^------------------------------------------- semantic version -----------------------------------------------------------^\n\n\" match incompatible pseudo versions\n\" incompatible without a major version before the commit (e.g.  vX.0.0-yyyymmddhhmmss-abcdefabcdef)\nsyntax match gomodVersion \"v[2-9]\\{1}\\d*\\.0\\.0-\\d\\{14\\}-\\x\\++incompatible\"\n\" when most recent version before target is a pre-release\nsyntax match gomodVersion \"v[2-9]\\{1}\\d*\\.\\d\\+\\.\\d\\+-\\%([0-9A-Za-z-]\\+\\)\\%(\\.[0-9A-Za-z-]\\+\\)*\\%(+\\%([0-9A-Za-z-]\\+\\)\\(\\.[0-9A-Za-z-]\\+\\)*\\)\\?\\.0\\.\\d\\{14}-\\x\\++incompatible\"\n\"                          ^------- version -------^^---------- pre-release -----------------^^--------------- metadata ---------------------^\n\"                     \t   ^---------------------------------------- semantic version ------------------------------------------------------^\n\" most recent version before the target is X.Y.Z\nsyntax match gomodVersion \"v[2-9]\\{1}\\d*\\.\\d\\+\\.\\d\\+\\%(+\\%([0-9A-Za-z-]\\+\\)\\%(\\.[0-9A-Za-z-]\\+\\)*\\)\\?-0\\.\\d\\{14}-\\x\\++incompatible\"\n\"                          ^------- version -------^^---------------- metadata ---------------------^\nhighlight default link gomodVersion Identifier\n\n\" match go version ranges in retract directive\n\" https://golang.org/ref/mod#go-mod-file-retract\nsyntax region gomodVersionRange start=\"\\[\" end=\"\\]\" transparent matchgroup=gomodVersionRangeBracket contains=gomodVersion,gomodVersionRangeSeparator\nhighlight default link gomodVersionRange Operator\nsyntax match gomodVersionRangeBracket \"\\[\" contained\nsyntax match gomodVersionRangeBracket \"\\]\" contained\nhighlight default link gomodVersionRangeBracket Operator\nsyntax match gomodVersionRangeSeparator \",\" contained\nhighlight default link gomodVersionRangeSeparator Operator\n\n\nlet b:current_syntax = \"gomod\"\n"
  },
  {
    "path": "syntax/gosum.vim",
    "content": "\" gosum.vim: Vim syntax file for go.sum file\n\"\n\" Quit when a (custom) syntax file was already loaded\nif exists(\"b:current_syntax\")\n  finish\nendif\n\nsyntax case match\n\n\" highlight versions:\n\"  * vX.Y.Z-pre\n\"  * vX.Y.Z\n\"  * vX.0.0-yyyyymmddhhmmss-abcdefabcdef\n\"  * vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef\n\"  * vX.Y.(Z+1)-0.yyyymmddhhss-abcdefabcdef\n\"  see https://godoc.org/golang.org/x/tools/internal/semver for more\n\"  information about how semantic versions are parsed and\n\"  https://golang.org/cmd/go/ for how pseudo-versions and +incompatible\n\"  are applied.\n\n\n\" match vX.Y.Z and their prereleases\nsyntax match gomodVersion \"v\\d\\+\\.\\d\\+\\.\\d\\+\\%(-\\%([0-9A-Za-z-]\\+\\)\\%(\\.[0-9A-Za-z-]\\+\\)*\\)\\?\\%(+\\%([0-9A-Za-z-]\\+\\)\\(\\.[0-9A-Za-z-]\\+\\)*\\)\\?\"\n\"                          ^--- version ---^^------------ pre-release  ---------------------^^--------------- metadata ---------------------^\n\"   \t                     ^--------------------------------------- semantic version -------------------------------------------------------^\n\n\" match pseudo versions\n\" without a major version before the commit (e.g.  vX.0.0-yyyymmddhhmmss-abcdefabcdef)\nsyntax match gomodVersion  \"v\\d\\+\\.0\\.0-\\d\\{14\\}-\\x\\+\"\n\" when most recent version before target is a pre-release\nsyntax match gomodVersion  \"v\\d\\+\\.\\d\\+\\.\\d\\+-\\%([0-9A-Za-z-]\\+\\)\\%(\\.[0-9A-Za-z-]\\+\\)*\\%(+\\%([0-9A-Za-z-]\\+\\)\\(\\.[0-9A-Za-z-]\\+\\)*\\)\\?\\.0\\.\\d\\{14}-\\x\\+\"\n\"                          ^--- version ---^^--- ------ pre-release -----------------^^--------------- metadata ---------------------^\n\"                     \t   ^------------------------------------- semantic version --------------------------------------------------^\n\" most recent version before the target is X.Y.Z\nsyntax match gomodVersion \"v\\d\\+\\.\\d\\+\\.\\d\\+\\%(+\\%([0-9A-Za-z-]\\+\\)\\(\\.[0-9A-Za-z-]\\+\\)*\\)\\?-0\\.\\d\\{14}-\\x\\+\"\n\"                          ^--- version ---^^--------------- metadata ---------------------^\n\n\" match incompatible vX.Y.Z and their prereleases\nsyntax match gomodVersion \"v[2-9]\\{1}\\d*\\.\\d\\+\\.\\d\\+\\%(-\\%([0-9A-Za-z-]\\+\\)\\%(\\.[0-9A-Za-z-]\\+\\)*\\)\\?\\%(+\\%([0-9A-Za-z-]\\+\\)\\(\\.[0-9A-Za-z-]\\+\\)*\\)\\?+incompatible\"\n\"                          ^------- version -------^^------------- pre-release ---------------------^^--------------- metadata ---------------------^\n\"               \t         ^------------------------------------------- semantic version -----------------------------------------------------------^\n\n\" match incompatible pseudo versions\n\" incompatible without a major version before the commit (e.g.  vX.0.0-yyyymmddhhmmss-abcdefabcdef)\nsyntax match gomodVersion \"v[2-9]\\{1}\\d*\\.0\\.0-\\d\\{14\\}-\\x\\++incompatible\"\n\" when most recent version before target is a pre-release\nsyntax match gomodVersion \"v[2-9]\\{1}\\d*\\.\\d\\+\\.\\d\\+-\\%([0-9A-Za-z-]\\+\\)\\%(\\.[0-9A-Za-z-]\\+\\)*\\%(+\\%([0-9A-Za-z-]\\+\\)\\(\\.[0-9A-Za-z-]\\+\\)*\\)\\?\\.0\\.\\d\\{14}-\\x\\++incompatible\"\n\"                          ^------- version -------^^---------- pre-release -----------------^^--------------- metadata ---------------------^\n\"                     \t   ^---------------------------------------- semantic version ------------------------------------------------------^\n\" most recent version before the target is X.Y.Z\nsyntax match gomodVersion \"v[2-9]\\{1}\\d*\\.\\d\\+\\.\\d\\+\\%(+\\%([0-9A-Za-z-]\\+\\)\\%(\\.[0-9A-Za-z-]\\+\\)*\\)\\?-0\\.\\d\\{14}-\\x\\++incompatible\"\n\"                          ^------- version -------^^---------------- metadata ---------------------^\nhighlight default link gomodVersion Identifier\n\nlet b:current_syntax = \"gomod\"\n"
  },
  {
    "path": "syntax/gotexttmpl.vim",
    "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\" gotexttmpl.vim: Vim syntax file for Go templates.\n\n\" Quit when a (custom) syntax file was already loaded\nif exists(\"b:current_syntax\")\n  finish\nendif\n\nsyn case match\n\n\" Go escapes\nsyn match       goEscapeOctal       display contained \"\\\\[0-7]\\{3}\"\nsyn match       goEscapeC           display contained +\\\\[abfnrtv\\\\'\"]+\nsyn match       goEscapeX           display contained \"\\\\x\\x\\{2}\"\nsyn match       goEscapeU           display contained \"\\\\u\\x\\{4}\"\nsyn match       goEscapeBigU        display contained \"\\\\U\\x\\{8}\"\nsyn match       goEscapeError       display contained +\\\\[^0-7xuUabfnrtv\\\\'\"]+\n\nhi def link     goEscapeOctal       goSpecialString\nhi def link     goEscapeC           goSpecialString\nhi def link     goEscapeX           goSpecialString\nhi def link     goEscapeU           goSpecialString\nhi def link     goEscapeBigU        goSpecialString\nhi def link     goSpecialString     Special\nhi def link     goEscapeError       Error\n\n\" Strings and their contents\nsyn cluster     goStringGroup       contains=goEscapeOctal,goEscapeC,goEscapeX,goEscapeU,goEscapeBigU,goEscapeError\nsyn region      goString            contained start=+\"+ skip=+\\\\\\\\\\|\\\\\"+ end=+\"+ contains=@goStringGroup\nsyn region      goRawString         contained start=+`+ end=+`+\n\nhi def link     goString            String\nhi def link     goRawString         String\n\n\" Characters; their contents\nsyn cluster     goCharacterGroup    contains=goEscapeOctal,goEscapeC,goEscapeX,goEscapeU,goEscapeBigU\nsyn region      goCharacter         contained start=+'+ skip=+\\\\\\\\\\|\\\\'+ end=+'+ contains=@goCharacterGroup\n\nhi def link     goCharacter         Character\n\n\" Integers\nsyn match       goDecimalInt        contained \"\\<\\d\\+\\([Ee]\\d\\+\\)\\?\\>\"\nsyn match       goHexadecimalInt    contained \"\\<0x\\x\\+\\>\"\nsyn match       goOctalInt          contained \"\\<0\\o\\+\\>\"\nsyn match       goOctalError        contained \"\\<0\\o*[89]\\d*\\>\"\nsyn cluster     goInt               contains=goDecimalInt,goHexadecimalInt,goOctalInt\n\" Floating point\nsyn match       goFloat             contained \"\\<\\d\\+\\.\\d*\\([Ee][-+]\\d\\+\\)\\?\\>\"\nsyn match       goFloat             contained \"\\<\\.\\d\\+\\([Ee][-+]\\d\\+\\)\\?\\>\"\nsyn match       goFloat             contained \"\\<\\d\\+[Ee][-+]\\d\\+\\>\"\n\" Imaginary literals\nsyn match       goImaginary         contained \"\\<\\d\\+i\\>\"\nsyn match       goImaginary         contained \"\\<\\d\\+\\.\\d*\\([Ee][-+]\\d\\+\\)\\?i\\>\"\nsyn match       goImaginary         contained \"\\<\\.\\d\\+\\([Ee][-+]\\d\\+\\)\\?i\\>\"\nsyn match       goImaginary         contained \"\\<\\d\\+[Ee][-+]\\d\\+i\\>\"\n\nhi def link     goInt        Number\nhi def link     goFloat      Number\nhi def link     goImaginary  Number\n\n\" Token groups\nsyn cluster     gotplLiteral     contains=goString,goRawString,goCharacter,@goInt,goFloat,goImaginary\nsyn keyword     gotplControl     contained   if else end range with template\nsyn keyword     gotplFunctions   contained   and html index js len not or print printf println urlquery eq ne lt le gt ge\nsyn match       gotplVariable    contained   /\\$[a-zA-Z0-9_]*\\>/\nsyn match       goTplIdentifier  contained   /\\.[^[:blank:]}]\\+\\>/\n\nhi def link     gotplControl        Keyword\nhi def link     gotplFunctions      Function\nhi def link     goTplVariable       Special\n\nsyn region gotplAction start=\"{{\" end=\"}}\" contains=@gotplLiteral,gotplControl,gotplFunctions,gotplVariable,goTplIdentifier display\nsyn region goTplComment start=\"{{\\(- \\)\\?/\\*\" end=\"\\*/\\( -\\)\\?}}\" display\n\nhi def link gotplAction PreProc\nhi def link goTplComment Comment\n\nlet b:current_syntax = \"gotexttmpl\"\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "syntax/gowork.vim",
    "content": "\" gowork.vim: Vim syntax file for go.work file\n\"\n\" Quit when a (custom) syntax file was already loaded\nif exists(\"b:current_syntax\")\n  finish\nendif\n\nsyntax case match\n\n\" Reference documentation:\n\" https://go.dev/ref/mod#workspaces\n\n\" match keywords\nsyntax keyword goworkGo      go      contained\nsyntax keyword goworkUse     use\nsyntax keyword goworkReplace replace\n\n\" use, exclude, replace, and go can be also grouped into block\nsyntax region goworkUse     start='use (' end=')'     transparent contains=goworkUse\nsyntax region goworkReplace start='replace (' end=')' transparent contains=goworkReplace,goworkVersion\nsyntax match  goworkGo            '^go .*$'           transparent contains=goworkGo,goworkGoVersion\n\n\" set highlights\nhighlight default link goworkGo      Keyword\nhighlight default link goworkUse     Keyword\nhighlight default link goworkReplace Keyword\n\n\" comments are always in form of // ...\nsyntax region goworkComment  start=\"//\" end=\"$\" contains=@Spell\nhighlight default link goworkComment Comment\n\n\" make sure quoted import paths are higlighted\nsyntax region goworkString start=+\"+ skip=+\\\\\\\\\\|\\\\\"+ end=+\"+ \nhighlight default link goworkString  String \n\n\" replace operator is in the form of '=>'\nsyntax match goworkReplaceOperator \"\\v\\=\\>\"\nhighlight default link goworkReplaceOperator Operator\n\n\" match go versions\nsyntax match goworkGoVersion \"1\\.\\d\\+\" contained\nhighlight default link goworkGoVersion Identifier\n\n\" highlight versions:\n\"  * vX.Y.Z-pre\n\"  * vX.Y.Z\n\"  * vX.0.0-yyyyymmddhhmmss-abcdefabcdef\n\"  * vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef\n\"  * vX.Y.(Z+1)-0.yyyymmddhhss-abcdefabcdef\n\"  see https://godoc.org/golang.org/x/tools/internal/semver for more\n\"  information about how semantic versions are parsed and\n\"  https://golang.org/cmd/go/ for how pseudo-versions and +incompatible\n\"  are applied.\n\n\n\" match vX.Y.Z and their prereleases\nsyntax match goworkVersion \"v\\d\\+\\.\\d\\+\\.\\d\\+\\%(-\\%([0-9A-Za-z-]\\+\\)\\%(\\.[0-9A-Za-z-]\\+\\)*\\)\\?\\%(+\\%([0-9A-Za-z-]\\+\\)\\(\\.[0-9A-Za-z-]\\+\\)*\\)\\?\"\n\"                          ^--- version ---^^------------ pre-release  ---------------------^^--------------- metadata ---------------------^\n\"   \t                     ^--------------------------------------- semantic version -------------------------------------------------------^\n\n\" match pseudo versions\n\" without a major version before the commit (e.g.  vX.0.0-yyyymmddhhmmss-abcdefabcdef)\nsyntax match goworkVersion  \"v\\d\\+\\.0\\.0-\\d\\{14\\}-\\x\\+\"\n\" when most recent version before target is a pre-release\nsyntax match goworkVersion  \"v\\d\\+\\.\\d\\+\\.\\d\\+-\\%([0-9A-Za-z-]\\+\\)\\%(\\.[0-9A-Za-z-]\\+\\)*\\%(+\\%([0-9A-Za-z-]\\+\\)\\(\\.[0-9A-Za-z-]\\+\\)*\\)\\?\\.0\\.\\d\\{14}-\\x\\+\"\n\"                          ^--- version ---^^--- ------ pre-release -----------------^^--------------- metadata ---------------------^\n\"                     \t   ^------------------------------------- semantic version --------------------------------------------------^\n\" most recent version before the target is X.Y.Z\nsyntax match goworkVersion \"v\\d\\+\\.\\d\\+\\.\\d\\+\\%(+\\%([0-9A-Za-z-]\\+\\)\\(\\.[0-9A-Za-z-]\\+\\)*\\)\\?-0\\.\\d\\{14}-\\x\\+\"\n\"                          ^--- version ---^^--------------- metadata ---------------------^\n\n\" match incompatible vX.Y.Z and their prereleases\nsyntax match goworkVersion \"v[2-9]\\{1}\\d*\\.\\d\\+\\.\\d\\+\\%(-\\%([0-9A-Za-z-]\\+\\)\\%(\\.[0-9A-Za-z-]\\+\\)*\\)\\?\\%(+\\%([0-9A-Za-z-]\\+\\)\\(\\.[0-9A-Za-z-]\\+\\)*\\)\\?+incompatible\"\n\"                          ^------- version -------^^------------- pre-release ---------------------^^--------------- metadata ---------------------^\n\"               \t         ^------------------------------------------- semantic version -----------------------------------------------------------^\n\n\" match incompatible pseudo versions\n\" incompatible without a major version before the commit (e.g.  vX.0.0-yyyymmddhhmmss-abcdefabcdef)\nsyntax match goworkVersion \"v[2-9]\\{1}\\d*\\.0\\.0-\\d\\{14\\}-\\x\\++incompatible\"\n\" when most recent version before target is a pre-release\nsyntax match goworkVersion \"v[2-9]\\{1}\\d*\\.\\d\\+\\.\\d\\+-\\%([0-9A-Za-z-]\\+\\)\\%(\\.[0-9A-Za-z-]\\+\\)*\\%(+\\%([0-9A-Za-z-]\\+\\)\\(\\.[0-9A-Za-z-]\\+\\)*\\)\\?\\.0\\.\\d\\{14}-\\x\\++incompatible\"\n\"                          ^------- version -------^^---------- pre-release -----------------^^--------------- metadata ---------------------^\n\"                     \t   ^---------------------------------------- semantic version ------------------------------------------------------^\n\" most recent version before the target is X.Y.Z\nsyntax match goworkVersion \"v[2-9]\\{1}\\d*\\.\\d\\+\\.\\d\\+\\%(+\\%([0-9A-Za-z-]\\+\\)\\%(\\.[0-9A-Za-z-]\\+\\)*\\)\\?-0\\.\\d\\{14}-\\x\\++incompatible\"\n\"                          ^------- version -------^^---------------- metadata ---------------------^\nhighlight default link goworkVersion Identifier\n\nlet b:current_syntax = \"gowork\"\n"
  },
  {
    "path": "syntax/vimgo.vim",
    "content": "if exists(\"b:current_syntax\")\n  finish\nendif\n\nlet b:current_syntax = \"vimgo\"\n\nsyn match   goInterface /^\\S*/\nsyn region  goTitle start=\"\\%1l\" end=\":\"\n\nhi def link goInterface Type\nhi def link goTitle Label\n\n\" vim: sw=2 ts=2 et\n"
  },
  {
    "path": "templates/hello_world.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"vim-go\")\n}\n"
  },
  {
    "path": "templates/hello_world_test.go",
    "content": "package main\n\nimport \"testing\"\n\nfunc TestHelloWorld(t *testing.T) {\n\t// t.Fatal(\"not implemented\")\n}\n"
  },
  {
    "path": "test/parse.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// golang.org/x/net/html/parse.go\n\npackage html\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"strings\"\n\n\ta \"golang.org/x/net/html/atom\"\n)\n\n// A parser implements the HTML5 parsing algorithm:\n// https://html.spec.whatwg.org/multipage/syntax.html#tree-construction\ntype parser struct {\n\t// tokenizer provides the tokens for the parser.\n\ttokenizer *Tokenizer\n\t// tok is the most recently read token.\n\ttok Token\n\t// Self-closing tags like <hr/> are treated as start tags, except that\n\t// hasSelfClosingToken is set while they are being processed.\n\thasSelfClosingToken bool\n\t// doc is the document root element.\n\tdoc *Node\n\t// The stack of open elements (section 12.2.3.2) and active formatting\n\t// elements (section 12.2.3.3).\n\toe, afe nodeStack\n\t// Element pointers (section 12.2.3.4).\n\thead, form *Node\n\t// Other parsing state flags (section 12.2.3.5).\n\tscripting, framesetOK bool\n\t// im is the current insertion mode.\n\tim insertionMode\n\t// originalIM is the insertion mode to go back to after completing a text\n\t// or inTableText insertion mode.\n\toriginalIM insertionMode\n\t// fosterParenting is whether new elements should be inserted according to\n\t// the foster parenting rules (section 12.2.5.3).\n\tfosterParenting bool\n\t// quirks is whether the parser is operating in \"quirks mode.\"\n\tquirks bool\n\t// fragment is whether the parser is parsing an HTML fragment.\n\tfragment bool\n\t// context is the context element when parsing an HTML fragment\n\t// (section 12.4).\n\tcontext *Node\n}\n\nfunc (p *parser) top() *Node {\n\tif n := p.oe.top(); n != nil {\n\t\treturn n\n\t}\n\treturn p.doc\n}\n\n// Stop tags for use in popUntil. These come from section 12.2.3.2.\nvar (\n\tdefaultScopeStopTags = map[string][]a.Atom{\n\t\t\"\":     {a.Applet, a.Caption, a.Html, a.Table, a.Td, a.Th, a.Marquee, a.Object, a.Template},\n\t\t\"math\": {a.AnnotationXml, a.Mi, a.Mn, a.Mo, a.Ms, a.Mtext},\n\t\t\"svg\":  {a.Desc, a.ForeignObject, a.Title},\n\t}\n)\n\ntype scope int\n\nconst (\n\tdefaultScope scope = iota\n\tlistItemScope\n\tbuttonScope\n\ttableScope\n\ttableRowScope\n\ttableBodyScope\n\tselectScope\n)\n\n// popUntil pops the stack of open elements at the highest element whose tag\n// is in matchTags, provided there is no higher element in the scope's stop\n// tags (as defined in section 12.2.3.2). It returns whether or not there was\n// such an element. If there was not, popUntil leaves the stack unchanged.\n//\n// For example, the set of stop tags for table scope is: \"html\", \"table\". If\n// the stack was:\n// [\"html\", \"body\", \"font\", \"table\", \"b\", \"i\", \"u\"]\n// then popUntil(tableScope, \"font\") would return false, but\n// popUntil(tableScope, \"i\") would return true and the stack would become:\n// [\"html\", \"body\", \"font\", \"table\", \"b\"]\n//\n// If an element's tag is in both the stop tags and matchTags, then the stack\n// will be popped and the function returns true (provided, of course, there was\n// no higher element in the stack that was also in the stop tags). For example,\n// popUntil(tableScope, \"table\") returns true and leaves:\n// [\"html\", \"body\", \"font\"]\nfunc (p *parser) popUntil(s scope, matchTags ...a.Atom) bool {\n\tif i := p.indexOfElementInScope(s, matchTags...); i != -1 {\n\t\tp.oe = p.oe[:i]\n\t\treturn true\n\t}\n\treturn false\n}\n\n// indexOfElementInScope returns the index in p.oe of the highest element whose\n// tag is in matchTags that is in scope. If no matching element is in scope, it\n// returns -1.\nfunc (p *parser) indexOfElementInScope(s scope, matchTags ...a.Atom) int {\n\tfor i := len(p.oe) - 1; i >= 0; i-- {\n\t\ttagAtom := p.oe[i].DataAtom\n\t\tif p.oe[i].Namespace == \"\" {\n\t\t\tfor _, t := range matchTags {\n\t\t\t\tif t == tagAtom {\n\t\t\t\t\treturn i\n\t\t\t\t}\n\t\t\t}\n\t\t\tswitch s {\n\t\t\tcase defaultScope:\n\t\t\t\t// No-op.\n\t\t\tcase listItemScope:\n\t\t\t\tif tagAtom == a.Ol || tagAtom == a.Ul {\n\t\t\t\t\treturn -1\n\t\t\t\t}\n\t\t\tcase buttonScope:\n\t\t\t\tif tagAtom == a.Button {\n\t\t\t\t\treturn -1\n\t\t\t\t}\n\t\t\tcase tableScope:\n\t\t\t\tif tagAtom == a.Html || tagAtom == a.Table {\n\t\t\t\t\treturn -1\n\t\t\t\t}\n\t\t\tcase selectScope:\n\t\t\t\tif tagAtom != a.Optgroup && tagAtom != a.Option {\n\t\t\t\t\treturn -1\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\tpanic(\"unreachable\")\n\t\t\t}\n\t\t}\n\t\tswitch s {\n\t\tcase defaultScope, listItemScope, buttonScope:\n\t\t\tfor _, t := range defaultScopeStopTags[p.oe[i].Namespace] {\n\t\t\t\tif t == tagAtom {\n\t\t\t\t\treturn -1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn -1\n}\n\n// elementInScope is like popUntil, except that it doesn't modify the stack of\n// open elements.\nfunc (p *parser) elementInScope(s scope, matchTags ...a.Atom) bool {\n\treturn p.indexOfElementInScope(s, matchTags...) != -1\n}\n\n// clearStackToContext pops elements off the stack of open elements until a\n// scope-defined element is found.\nfunc (p *parser) clearStackToContext(s scope) {\n\tfor i := len(p.oe) - 1; i >= 0; i-- {\n\t\ttagAtom := p.oe[i].DataAtom\n\t\tswitch s {\n\t\tcase tableScope:\n\t\t\tif tagAtom == a.Html || tagAtom == a.Table {\n\t\t\t\tp.oe = p.oe[:i+1]\n\t\t\t\treturn\n\t\t\t}\n\t\tcase tableRowScope:\n\t\t\tif tagAtom == a.Html || tagAtom == a.Tr {\n\t\t\t\tp.oe = p.oe[:i+1]\n\t\t\t\treturn\n\t\t\t}\n\t\tcase tableBodyScope:\n\t\t\tif tagAtom == a.Html || tagAtom == a.Tbody || tagAtom == a.Tfoot || tagAtom == a.Thead {\n\t\t\t\tp.oe = p.oe[:i+1]\n\t\t\t\treturn\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unreachable\")\n\t\t}\n\t}\n}\n\n// generateImpliedEndTags pops nodes off the stack of open elements as long as\n// the top node has a tag name of dd, dt, li, option, optgroup, p, rp, or rt.\n// If exceptions are specified, nodes with that name will not be popped off.\nfunc (p *parser) generateImpliedEndTags(exceptions ...string) {\n\tvar i int\nloop:\n\tfor i = len(p.oe) - 1; i >= 0; i-- {\n\t\tn := p.oe[i]\n\t\tif n.Type == ElementNode {\n\t\t\tswitch n.DataAtom {\n\t\t\tcase a.Dd, a.Dt, a.Li, a.Option, a.Optgroup, a.P, a.Rp, a.Rt:\n\t\t\t\tfor _, except := range exceptions {\n\t\t\t\t\tif n.Data == except {\n\t\t\t\t\t\tbreak loop\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tbreak\n\t}\n\n\tp.oe = p.oe[:i+1]\n}\n\n// addChild adds a child node n to the top element, and pushes n onto the stack\n// of open elements if it is an element node.\nfunc (p *parser) addChild(n *Node) {\n\tif p.shouldFosterParent() {\n\t\tp.fosterParent(n)\n\t} else {\n\t\tp.top().AppendChild(n)\n\t}\n\n\tif n.Type == ElementNode {\n\t\tp.oe = append(p.oe, n)\n\t}\n}\n\n// shouldFosterParent returns whether the next node to be added should be\n// foster parented.\nfunc (p *parser) shouldFosterParent() bool {\n\tif p.fosterParenting {\n\t\tswitch p.top().DataAtom {\n\t\tcase a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// fosterParent adds a child node according to the foster parenting rules.\n// Section 12.2.5.3, \"foster parenting\".\nfunc (p *parser) fosterParent(n *Node) {\n\tvar table, parent, prev *Node\n\tvar i int\n\tfor i = len(p.oe) - 1; i >= 0; i-- {\n\t\tif p.oe[i].DataAtom == a.Table {\n\t\t\ttable = p.oe[i]\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif table == nil {\n\t\t// The foster parent is the html element.\n\t\tparent = p.oe[0]\n\t} else {\n\t\tparent = table.Parent\n\t}\n\tif parent == nil {\n\t\tparent = p.oe[i-1]\n\t}\n\n\tif table != nil {\n\t\tprev = table.PrevSibling\n\t} else {\n\t\tprev = parent.LastChild\n\t}\n\tif prev != nil && prev.Type == TextNode && n.Type == TextNode {\n\t\tprev.Data += n.Data\n\t\treturn\n\t}\n\n\tparent.InsertBefore(n, table)\n}\n\n// addText adds text to the preceding node if it is a text node, or else it\n// calls addChild with a new text node.\nfunc (p *parser) addText(text string) {\n\tif text == \"\" {\n\t\treturn\n\t}\n\n\tif p.shouldFosterParent() {\n\t\tp.fosterParent(&Node{\n\t\t\tType: TextNode,\n\t\t\tData: text,\n\t\t})\n\t\treturn\n\t}\n\n\tt := p.top()\n\tif n := t.LastChild; n != nil && n.Type == TextNode {\n\t\tn.Data += text\n\t\treturn\n\t}\n\tp.addChild(&Node{\n\t\tType: TextNode,\n\t\tData: text,\n\t})\n}\n\n// addElement adds a child element based on the current token.\nfunc (p *parser) addElement() {\n\tp.addChild(&Node{\n\t\tType:     ElementNode,\n\t\tDataAtom: p.tok.DataAtom,\n\t\tData:     p.tok.Data,\n\t\tAttr:     p.tok.Attr,\n\t})\n}\n\n// Section 12.2.3.3.\nfunc (p *parser) addFormattingElement() {\n\ttagAtom, attr := p.tok.DataAtom, p.tok.Attr\n\tp.addElement()\n\n\t// Implement the Noah's Ark clause, but with three per family instead of two.\n\tidenticalElements := 0\nfindIdenticalElements:\n\tfor i := len(p.afe) - 1; i >= 0; i-- {\n\t\tn := p.afe[i]\n\t\tif n.Type == scopeMarkerNode {\n\t\t\tbreak\n\t\t}\n\t\tif n.Type != ElementNode {\n\t\t\tcontinue\n\t\t}\n\t\tif n.Namespace != \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tif n.DataAtom != tagAtom {\n\t\t\tcontinue\n\t\t}\n\t\tif len(n.Attr) != len(attr) {\n\t\t\tcontinue\n\t\t}\n\tcompareAttributes:\n\t\tfor _, t0 := range n.Attr {\n\t\t\tfor _, t1 := range attr {\n\t\t\t\tif t0.Key == t1.Key && t0.Namespace == t1.Namespace && t0.Val == t1.Val {\n\t\t\t\t\t// Found a match for this attribute, continue with the next attribute.\n\t\t\t\t\tcontinue compareAttributes\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we get here, there is no attribute that matches a.\n\t\t\t// Therefore the element is not identical to the new one.\n\t\t\tcontinue findIdenticalElements\n\t\t}\n\n\t\tidenticalElements++\n\t\tif identicalElements >= 3 {\n\t\t\tp.afe.remove(n)\n\t\t}\n\t}\n\n\tp.afe = append(p.afe, p.top())\n}\n\n// Section 12.2.3.3.\nfunc (p *parser) clearActiveFormattingElements() {\n\tfor {\n\t\tn := p.afe.pop()\n\t\tif len(p.afe) == 0 || n.Type == scopeMarkerNode {\n\t\t\treturn\n\t\t}\n\t}\n}\n\n// Section 12.2.3.3.\nfunc (p *parser) reconstructActiveFormattingElements() {\n\tn := p.afe.top()\n\tif n == nil {\n\t\treturn\n\t}\n\tif n.Type == scopeMarkerNode || p.oe.index(n) != -1 {\n\t\treturn\n\t}\n\ti := len(p.afe) - 1\n\tfor n.Type != scopeMarkerNode && p.oe.index(n) == -1 {\n\t\tif i == 0 {\n\t\t\ti = -1\n\t\t\tbreak\n\t\t}\n\t\ti--\n\t\tn = p.afe[i]\n\t}\n\tfor {\n\t\ti++\n\t\tclone := p.afe[i].clone()\n\t\tp.addChild(clone)\n\t\tp.afe[i] = clone\n\t\tif i == len(p.afe)-1 {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\n// Section 12.2.4.\nfunc (p *parser) acknowledgeSelfClosingTag() {\n\tp.hasSelfClosingToken = false\n}\n\n// An insertion mode (section 12.2.3.1) is the state transition function from\n// a particular state in the HTML5 parser's state machine. It updates the\n// parser's fields depending on parser.tok (where ErrorToken means EOF).\n// It returns whether the token was consumed.\ntype insertionMode func(*parser) bool\n\n// setOriginalIM sets the insertion mode to return to after completing a text or\n// inTableText insertion mode.\n// Section 12.2.3.1, \"using the rules for\".\nfunc (p *parser) setOriginalIM() {\n\tif p.originalIM != nil {\n\t\tpanic(\"html: bad parser state: originalIM was set twice\")\n\t}\n\tp.originalIM = p.im\n}\n\n// Section 12.2.3.1, \"reset the insertion mode\".\nfunc (p *parser) resetInsertionMode() {\n\tfor i := len(p.oe) - 1; i >= 0; i-- {\n\t\tn := p.oe[i]\n\t\tif i == 0 && p.context != nil {\n\t\t\tn = p.context\n\t\t}\n\n\t\tswitch n.DataAtom {\n\t\tcase a.Select:\n\t\t\tp.im = inSelectIM\n\t\tcase a.Td, a.Th:\n\t\t\tp.im = inCellIM\n\t\tcase a.Tr:\n\t\t\tp.im = inRowIM\n\t\tcase a.Tbody, a.Thead, a.Tfoot:\n\t\t\tp.im = inTableBodyIM\n\t\tcase a.Caption:\n\t\t\tp.im = inCaptionIM\n\t\tcase a.Colgroup:\n\t\t\tp.im = inColumnGroupIM\n\t\tcase a.Table:\n\t\t\tp.im = inTableIM\n\t\tcase a.Head:\n\t\t\tp.im = inBodyIM\n\t\tcase a.Body:\n\t\t\tp.im = inBodyIM\n\t\tcase a.Frameset:\n\t\t\tp.im = inFramesetIM\n\t\tcase a.Html:\n\t\t\tp.im = beforeHeadIM\n\t\tdefault:\n\t\t\tcontinue\n\t\t}\n\t\treturn\n\t}\n\tp.im = inBodyIM\n}\n\nconst whitespace = \" \\t\\r\\n\\f\"\n\n// Section 12.2.5.4.1.\nfunc initialIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase TextToken:\n\t\tp.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)\n\t\tif len(p.tok.Data) == 0 {\n\t\t\t// It was all whitespace, so ignore it.\n\t\t\treturn true\n\t\t}\n\tcase CommentToken:\n\t\tp.doc.AppendChild(&Node{\n\t\t\tType: CommentNode,\n\t\t\tData: p.tok.Data,\n\t\t})\n\t\treturn true\n\tcase DoctypeToken:\n\t\tn, quirks := parseDoctype(p.tok.Data)\n\t\tp.doc.AppendChild(n)\n\t\tp.quirks = quirks\n\t\tp.im = beforeHTMLIM\n\t\treturn true\n\t}\n\tp.quirks = true\n\tp.im = beforeHTMLIM\n\treturn false\n}\n\n// Section 12.2.5.4.2.\nfunc beforeHTMLIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase DoctypeToken:\n\t\t// Ignore the token.\n\t\treturn true\n\tcase TextToken:\n\t\tp.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)\n\t\tif len(p.tok.Data) == 0 {\n\t\t\t// It was all whitespace, so ignore it.\n\t\t\treturn true\n\t\t}\n\tcase StartTagToken:\n\t\tif p.tok.DataAtom == a.Html {\n\t\t\tp.addElement()\n\t\t\tp.im = beforeHeadIM\n\t\t\treturn true\n\t\t}\n\tcase EndTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Head, a.Body, a.Html, a.Br:\n\t\t\tp.parseImpliedToken(StartTagToken, a.Html, a.Html.String())\n\t\t\treturn false\n\t\tdefault:\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\t}\n\tcase CommentToken:\n\t\tp.doc.AppendChild(&Node{\n\t\t\tType: CommentNode,\n\t\t\tData: p.tok.Data,\n\t\t})\n\t\treturn true\n\t}\n\tp.parseImpliedToken(StartTagToken, a.Html, a.Html.String())\n\treturn false\n}\n\n// Section 12.2.5.4.3.\nfunc beforeHeadIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase TextToken:\n\t\tp.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)\n\t\tif len(p.tok.Data) == 0 {\n\t\t\t// It was all whitespace, so ignore it.\n\t\t\treturn true\n\t\t}\n\tcase StartTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Head:\n\t\t\tp.addElement()\n\t\t\tp.head = p.top()\n\t\t\tp.im = inHeadIM\n\t\t\treturn true\n\t\tcase a.Html:\n\t\t\treturn inBodyIM(p)\n\t\t}\n\tcase EndTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Head, a.Body, a.Html, a.Br:\n\t\t\tp.parseImpliedToken(StartTagToken, a.Head, a.Head.String())\n\t\t\treturn false\n\t\tdefault:\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\t}\n\tcase CommentToken:\n\t\tp.addChild(&Node{\n\t\t\tType: CommentNode,\n\t\t\tData: p.tok.Data,\n\t\t})\n\t\treturn true\n\tcase DoctypeToken:\n\t\t// Ignore the token.\n\t\treturn true\n\t}\n\n\tp.parseImpliedToken(StartTagToken, a.Head, a.Head.String())\n\treturn false\n}\n\n// Section 12.2.5.4.4.\nfunc inHeadIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase TextToken:\n\t\ts := strings.TrimLeft(p.tok.Data, whitespace)\n\t\tif len(s) < len(p.tok.Data) {\n\t\t\t// Add the initial whitespace to the current node.\n\t\t\tp.addText(p.tok.Data[:len(p.tok.Data)-len(s)])\n\t\t\tif s == \"\" {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tp.tok.Data = s\n\t\t}\n\tcase StartTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Html:\n\t\t\treturn inBodyIM(p)\n\t\tcase a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta:\n\t\t\tp.addElement()\n\t\t\tp.oe.pop()\n\t\t\tp.acknowledgeSelfClosingTag()\n\t\t\treturn true\n\t\tcase a.Script, a.Title, a.Noscript, a.Noframes, a.Style:\n\t\t\tp.addElement()\n\t\t\tp.setOriginalIM()\n\t\t\tp.im = textIM\n\t\t\treturn true\n\t\tcase a.Head:\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\t}\n\tcase EndTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Head:\n\t\t\tn := p.oe.pop()\n\t\t\tif n.DataAtom != a.Head {\n\t\t\t\tpanic(\"html: bad parser state: <head> element not found, in the in-head insertion mode\")\n\t\t\t}\n\t\t\tp.im = afterHeadIM\n\t\t\treturn true\n\t\tcase a.Body, a.Html, a.Br:\n\t\t\tp.parseImpliedToken(EndTagToken, a.Head, a.Head.String())\n\t\t\treturn false\n\t\tdefault:\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\t}\n\tcase CommentToken:\n\t\tp.addChild(&Node{\n\t\t\tType: CommentNode,\n\t\t\tData: p.tok.Data,\n\t\t})\n\t\treturn true\n\tcase DoctypeToken:\n\t\t// Ignore the token.\n\t\treturn true\n\t}\n\n\tp.parseImpliedToken(EndTagToken, a.Head, a.Head.String())\n\treturn false\n}\n\n// Section 12.2.5.4.6.\nfunc afterHeadIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase TextToken:\n\t\ts := strings.TrimLeft(p.tok.Data, whitespace)\n\t\tif len(s) < len(p.tok.Data) {\n\t\t\t// Add the initial whitespace to the current node.\n\t\t\tp.addText(p.tok.Data[:len(p.tok.Data)-len(s)])\n\t\t\tif s == \"\" {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tp.tok.Data = s\n\t\t}\n\tcase StartTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Html:\n\t\t\treturn inBodyIM(p)\n\t\tcase a.Body:\n\t\t\tp.addElement()\n\t\t\tp.framesetOK = false\n\t\t\tp.im = inBodyIM\n\t\t\treturn true\n\t\tcase a.Frameset:\n\t\t\tp.addElement()\n\t\t\tp.im = inFramesetIM\n\t\t\treturn true\n\t\tcase a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title:\n\t\t\tp.oe = append(p.oe, p.head)\n\t\t\tdefer p.oe.remove(p.head)\n\t\t\treturn inHeadIM(p)\n\t\tcase a.Head:\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\t}\n\tcase EndTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Body, a.Html, a.Br:\n\t\t\t// Drop down to creating an implied <body> tag.\n\t\tdefault:\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\t}\n\tcase CommentToken:\n\t\tp.addChild(&Node{\n\t\t\tType: CommentNode,\n\t\t\tData: p.tok.Data,\n\t\t})\n\t\treturn true\n\tcase DoctypeToken:\n\t\t// Ignore the token.\n\t\treturn true\n\t}\n\n\tp.parseImpliedToken(StartTagToken, a.Body, a.Body.String())\n\tp.framesetOK = true\n\treturn false\n}\n\n// copyAttributes copies attributes of src not found on dst to dst.\nfunc copyAttributes(dst *Node, src Token) {\n\tif len(src.Attr) == 0 {\n\t\treturn\n\t}\n\tattr := map[string]string{}\n\tfor _, t := range dst.Attr {\n\t\tattr[t.Key] = t.Val\n\t}\n\tfor _, t := range src.Attr {\n\t\tif _, ok := attr[t.Key]; !ok {\n\t\t\tdst.Attr = append(dst.Attr, t)\n\t\t\tattr[t.Key] = t.Val\n\t\t}\n\t}\n}\n\n// Section 12.2.5.4.7.\nfunc inBodyIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase TextToken:\n\t\td := p.tok.Data\n\t\tswitch n := p.oe.top(); n.DataAtom {\n\t\tcase a.Pre, a.Listing:\n\t\t\tif n.FirstChild == nil {\n\t\t\t\t// Ignore a newline at the start of a <pre> block.\n\t\t\t\tif d != \"\" && d[0] == '\\r' {\n\t\t\t\t\td = d[1:]\n\t\t\t\t}\n\t\t\t\tif d != \"\" && d[0] == '\\n' {\n\t\t\t\t\td = d[1:]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\td = strings.Replace(d, \"\\x00\", \"\", -1)\n\t\tif d == \"\" {\n\t\t\treturn true\n\t\t}\n\t\tp.reconstructActiveFormattingElements()\n\t\tp.addText(d)\n\t\tif p.framesetOK && strings.TrimLeft(d, whitespace) != \"\" {\n\t\t\t// There were non-whitespace characters inserted.\n\t\t\tp.framesetOK = false\n\t\t}\n\tcase StartTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Html:\n\t\t\tcopyAttributes(p.oe[0], p.tok)\n\t\tcase a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title:\n\t\t\treturn inHeadIM(p)\n\t\tcase a.Body:\n\t\t\tif len(p.oe) >= 2 {\n\t\t\t\tbody := p.oe[1]\n\t\t\t\tif body.Type == ElementNode && body.DataAtom == a.Body {\n\t\t\t\t\tp.framesetOK = false\n\t\t\t\t\tcopyAttributes(body, p.tok)\n\t\t\t\t}\n\t\t\t}\n\t\tcase a.Frameset:\n\t\t\tif !p.framesetOK || len(p.oe) < 2 || p.oe[1].DataAtom != a.Body {\n\t\t\t\t// Ignore the token.\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tbody := p.oe[1]\n\t\t\tif body.Parent != nil {\n\t\t\t\tbody.Parent.RemoveChild(body)\n\t\t\t}\n\t\t\tp.oe = p.oe[:1]\n\t\t\tp.addElement()\n\t\t\tp.im = inFramesetIM\n\t\t\treturn true\n\t\tcase a.Address, a.Article, a.Aside, a.Blockquote, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Menu, a.Nav, a.Ol, a.P, a.Section, a.Summary, a.Ul:\n\t\t\tp.popUntil(buttonScope, a.P)\n\t\t\tp.addElement()\n\t\tcase a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:\n\t\t\tp.popUntil(buttonScope, a.P)\n\t\t\tswitch n := p.top(); n.DataAtom {\n\t\t\tcase a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:\n\t\t\t\tp.oe.pop()\n\t\t\t}\n\t\t\tp.addElement()\n\t\tcase a.Pre, a.Listing:\n\t\t\tp.popUntil(buttonScope, a.P)\n\t\t\tp.addElement()\n\t\t\t// The newline, if any, will be dealt with by the TextToken case.\n\t\t\tp.framesetOK = false\n\t\tcase a.Form:\n\t\t\tif p.form == nil {\n\t\t\t\tp.popUntil(buttonScope, a.P)\n\t\t\t\tp.addElement()\n\t\t\t\tp.form = p.top()\n\t\t\t}\n\t\tcase a.Li:\n\t\t\tp.framesetOK = false\n\t\t\tfor i := len(p.oe) - 1; i >= 0; i-- {\n\t\t\t\tnode := p.oe[i]\n\t\t\t\tswitch node.DataAtom {\n\t\t\t\tcase a.Li:\n\t\t\t\t\tp.oe = p.oe[:i]\n\t\t\t\tcase a.Address, a.Div, a.P:\n\t\t\t\t\tcontinue\n\t\t\t\tdefault:\n\t\t\t\t\tif !isSpecialElement(node) {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tp.popUntil(buttonScope, a.P)\n\t\t\tp.addElement()\n\t\tcase a.Dd, a.Dt:\n\t\t\tp.framesetOK = false\n\t\t\tfor i := len(p.oe) - 1; i >= 0; i-- {\n\t\t\t\tnode := p.oe[i]\n\t\t\t\tswitch node.DataAtom {\n\t\t\t\tcase a.Dd, a.Dt:\n\t\t\t\t\tp.oe = p.oe[:i]\n\t\t\t\tcase a.Address, a.Div, a.P:\n\t\t\t\t\tcontinue\n\t\t\t\tdefault:\n\t\t\t\t\tif !isSpecialElement(node) {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tp.popUntil(buttonScope, a.P)\n\t\t\tp.addElement()\n\t\tcase a.Plaintext:\n\t\t\tp.popUntil(buttonScope, a.P)\n\t\t\tp.addElement()\n\t\tcase a.Button:\n\t\t\tp.popUntil(defaultScope, a.Button)\n\t\t\tp.reconstructActiveFormattingElements()\n\t\t\tp.addElement()\n\t\t\tp.framesetOK = false\n\t\tcase a.A:\n\t\t\tfor i := len(p.afe) - 1; i >= 0 && p.afe[i].Type != scopeMarkerNode; i-- {\n\t\t\t\tif n := p.afe[i]; n.Type == ElementNode && n.DataAtom == a.A {\n\t\t\t\t\tp.inBodyEndTagFormatting(a.A)\n\t\t\t\t\tp.oe.remove(n)\n\t\t\t\t\tp.afe.remove(n)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tp.reconstructActiveFormattingElements()\n\t\t\tp.addFormattingElement()\n\t\tcase a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U:\n\t\t\tp.reconstructActiveFormattingElements()\n\t\t\tp.addFormattingElement()\n\t\tcase a.Nobr:\n\t\t\tp.reconstructActiveFormattingElements()\n\t\t\tif p.elementInScope(defaultScope, a.Nobr) {\n\t\t\t\tp.inBodyEndTagFormatting(a.Nobr)\n\t\t\t\tp.reconstructActiveFormattingElements()\n\t\t\t}\n\t\t\tp.addFormattingElement()\n\t\tcase a.Applet, a.Marquee, a.Object:\n\t\t\tp.reconstructActiveFormattingElements()\n\t\t\tp.addElement()\n\t\t\tp.afe = append(p.afe, &scopeMarker)\n\t\t\tp.framesetOK = false\n\t\tcase a.Table:\n\t\t\tif !p.quirks {\n\t\t\t\tp.popUntil(buttonScope, a.P)\n\t\t\t}\n\t\t\tp.addElement()\n\t\t\tp.framesetOK = false\n\t\t\tp.im = inTableIM\n\t\t\treturn true\n\t\tcase a.Area, a.Br, a.Embed, a.Img, a.Input, a.Keygen, a.Wbr:\n\t\t\tp.reconstructActiveFormattingElements()\n\t\t\tp.addElement()\n\t\t\tp.oe.pop()\n\t\t\tp.acknowledgeSelfClosingTag()\n\t\t\tif p.tok.DataAtom == a.Input {\n\t\t\t\tfor _, t := range p.tok.Attr {\n\t\t\t\t\tif t.Key == \"type\" {\n\t\t\t\t\t\tif strings.ToLower(t.Val) == \"hidden\" {\n\t\t\t\t\t\t\t// Skip setting framesetOK = false\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}\n\t\t\t}\n\t\t\tp.framesetOK = false\n\t\tcase a.Param, a.Source, a.Track:\n\t\t\tp.addElement()\n\t\t\tp.oe.pop()\n\t\t\tp.acknowledgeSelfClosingTag()\n\t\tcase a.Hr:\n\t\t\tp.popUntil(buttonScope, a.P)\n\t\t\tp.addElement()\n\t\t\tp.oe.pop()\n\t\t\tp.acknowledgeSelfClosingTag()\n\t\t\tp.framesetOK = false\n\t\tcase a.Image:\n\t\t\tp.tok.DataAtom = a.Img\n\t\t\tp.tok.Data = a.Img.String()\n\t\t\treturn false\n\t\tcase a.Isindex:\n\t\t\tif p.form != nil {\n\t\t\t\t// Ignore the token.\n\t\t\t\treturn true\n\t\t\t}\n\t\t\taction := \"\"\n\t\t\tprompt := \"This is a searchable index. Enter search keywords: \"\n\t\t\tattr := []Attribute{{Key: \"name\", Val: \"isindex\"}}\n\t\t\tfor _, t := range p.tok.Attr {\n\t\t\t\tswitch t.Key {\n\t\t\t\tcase \"action\":\n\t\t\t\t\taction = t.Val\n\t\t\t\tcase \"name\":\n\t\t\t\t\t// Ignore the attribute.\n\t\t\t\tcase \"prompt\":\n\t\t\t\t\tprompt = t.Val\n\t\t\t\tdefault:\n\t\t\t\t\tattr = append(attr, t)\n\t\t\t\t}\n\t\t\t}\n\t\t\tp.acknowledgeSelfClosingTag()\n\t\t\tp.popUntil(buttonScope, a.P)\n\t\t\tp.parseImpliedToken(StartTagToken, a.Form, a.Form.String())\n\t\t\tif action != \"\" {\n\t\t\t\tp.form.Attr = []Attribute{{Key: \"action\", Val: action}}\n\t\t\t}\n\t\t\tp.parseImpliedToken(StartTagToken, a.Hr, a.Hr.String())\n\t\t\tp.parseImpliedToken(StartTagToken, a.Label, a.Label.String())\n\t\t\tp.addText(prompt)\n\t\t\tp.addChild(&Node{\n\t\t\t\tType:     ElementNode,\n\t\t\t\tDataAtom: a.Input,\n\t\t\t\tData:     a.Input.String(),\n\t\t\t\tAttr:     attr,\n\t\t\t})\n\t\t\tp.oe.pop()\n\t\t\tp.parseImpliedToken(EndTagToken, a.Label, a.Label.String())\n\t\t\tp.parseImpliedToken(StartTagToken, a.Hr, a.Hr.String())\n\t\t\tp.parseImpliedToken(EndTagToken, a.Form, a.Form.String())\n\t\tcase a.Textarea:\n\t\t\tp.addElement()\n\t\t\tp.setOriginalIM()\n\t\t\tp.framesetOK = false\n\t\t\tp.im = textIM\n\t\tcase a.Xmp:\n\t\t\tp.popUntil(buttonScope, a.P)\n\t\t\tp.reconstructActiveFormattingElements()\n\t\t\tp.framesetOK = false\n\t\t\tp.addElement()\n\t\t\tp.setOriginalIM()\n\t\t\tp.im = textIM\n\t\tcase a.Iframe:\n\t\t\tp.framesetOK = false\n\t\t\tp.addElement()\n\t\t\tp.setOriginalIM()\n\t\t\tp.im = textIM\n\t\tcase a.Noembed, a.Noscript:\n\t\t\tp.addElement()\n\t\t\tp.setOriginalIM()\n\t\t\tp.im = textIM\n\t\tcase a.Select:\n\t\t\tp.reconstructActiveFormattingElements()\n\t\t\tp.addElement()\n\t\t\tp.framesetOK = false\n\t\t\tp.im = inSelectIM\n\t\t\treturn true\n\t\tcase a.Optgroup, a.Option:\n\t\t\tif p.top().DataAtom == a.Option {\n\t\t\t\tp.oe.pop()\n\t\t\t}\n\t\t\tp.reconstructActiveFormattingElements()\n\t\t\tp.addElement()\n\t\tcase a.Rp, a.Rt:\n\t\t\tif p.elementInScope(defaultScope, a.Ruby) {\n\t\t\t\tp.generateImpliedEndTags()\n\t\t\t}\n\t\t\tp.addElement()\n\t\tcase a.Math, a.Svg:\n\t\t\tp.reconstructActiveFormattingElements()\n\t\t\tif p.tok.DataAtom == a.Math {\n\t\t\t\tadjustAttributeNames(p.tok.Attr, mathMLAttributeAdjustments)\n\t\t\t} else {\n\t\t\t\tadjustAttributeNames(p.tok.Attr, svgAttributeAdjustments)\n\t\t\t}\n\t\t\tadjustForeignAttributes(p.tok.Attr)\n\t\t\tp.addElement()\n\t\t\tp.top().Namespace = p.tok.Data\n\t\t\tif p.hasSelfClosingToken {\n\t\t\t\tp.oe.pop()\n\t\t\t\tp.acknowledgeSelfClosingTag()\n\t\t\t}\n\t\t\treturn true\n\t\tcase a.Caption, a.Col, a.Colgroup, a.Frame, a.Head, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:\n\t\t\t// Ignore the token.\n\t\tdefault:\n\t\t\tp.reconstructActiveFormattingElements()\n\t\t\tp.addElement()\n\t\t}\n\tcase EndTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Body:\n\t\t\tif p.elementInScope(defaultScope, a.Body) {\n\t\t\t\tp.im = afterBodyIM\n\t\t\t}\n\t\tcase a.Html:\n\t\t\tif p.elementInScope(defaultScope, a.Body) {\n\t\t\t\tp.parseImpliedToken(EndTagToken, a.Body, a.Body.String())\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn true\n\t\tcase a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul:\n\t\t\tp.popUntil(defaultScope, p.tok.DataAtom)\n\t\tcase a.Form:\n\t\t\tnode := p.form\n\t\t\tp.form = nil\n\t\t\ti := p.indexOfElementInScope(defaultScope, a.Form)\n\t\t\tif node == nil || i == -1 || p.oe[i] != node {\n\t\t\t\t// Ignore the token.\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tp.generateImpliedEndTags()\n\t\t\tp.oe.remove(node)\n\t\tcase a.P:\n\t\t\tif !p.elementInScope(buttonScope, a.P) {\n\t\t\t\tp.parseImpliedToken(StartTagToken, a.P, a.P.String())\n\t\t\t}\n\t\t\tp.popUntil(buttonScope, a.P)\n\t\tcase a.Li:\n\t\t\tp.popUntil(listItemScope, a.Li)\n\t\tcase a.Dd, a.Dt:\n\t\t\tp.popUntil(defaultScope, p.tok.DataAtom)\n\t\tcase a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:\n\t\t\tp.popUntil(defaultScope, a.H1, a.H2, a.H3, a.H4, a.H5, a.H6)\n\t\tcase a.A, a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.Nobr, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U:\n\t\t\tp.inBodyEndTagFormatting(p.tok.DataAtom)\n\t\tcase a.Applet, a.Marquee, a.Object:\n\t\t\tif p.popUntil(defaultScope, p.tok.DataAtom) {\n\t\t\t\tp.clearActiveFormattingElements()\n\t\t\t}\n\t\tcase a.Br:\n\t\t\tp.tok.Type = StartTagToken\n\t\t\treturn false\n\t\tdefault:\n\t\t\tp.inBodyEndTagOther(p.tok.DataAtom)\n\t\t}\n\tcase CommentToken:\n\t\tp.addChild(&Node{\n\t\t\tType: CommentNode,\n\t\t\tData: p.tok.Data,\n\t\t})\n\t}\n\n\treturn true\n}\n\nfunc (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) {\n\t// This is the \"adoption agency\" algorithm, described at\n\t// https://html.spec.whatwg.org/multipage/syntax.html#adoptionAgency\n\n\t// TODO: this is a fairly literal line-by-line translation of that algorithm.\n\t// Once the code successfully parses the comprehensive test suite, we should\n\t// refactor this code to be more idiomatic.\n\n\t// Steps 1-4. The outer loop.\n\tfor i := 0; i < 8; i++ {\n\t\t// Step 5. Find the formatting element.\n\t\tvar formattingElement *Node\n\t\tfor j := len(p.afe) - 1; j >= 0; j-- {\n\t\t\tif p.afe[j].Type == scopeMarkerNode {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif p.afe[j].DataAtom == tagAtom {\n\t\t\t\tformattingElement = p.afe[j]\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif formattingElement == nil {\n\t\t\tp.inBodyEndTagOther(tagAtom)\n\t\t\treturn\n\t\t}\n\t\tfeIndex := p.oe.index(formattingElement)\n\t\tif feIndex == -1 {\n\t\t\tp.afe.remove(formattingElement)\n\t\t\treturn\n\t\t}\n\t\tif !p.elementInScope(defaultScope, tagAtom) {\n\t\t\t// Ignore the tag.\n\t\t\treturn\n\t\t}\n\n\t\t// Steps 9-10. Find the furthest block.\n\t\tvar furthestBlock *Node\n\t\tfor _, e := range p.oe[feIndex:] {\n\t\t\tif isSpecialElement(e) {\n\t\t\t\tfurthestBlock = e\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif furthestBlock == nil {\n\t\t\te := p.oe.pop()\n\t\t\tfor e != formattingElement {\n\t\t\t\te = p.oe.pop()\n\t\t\t}\n\t\t\tp.afe.remove(e)\n\t\t\treturn\n\t\t}\n\n\t\t// Steps 11-12. Find the common ancestor and bookmark node.\n\t\tcommonAncestor := p.oe[feIndex-1]\n\t\tbookmark := p.afe.index(formattingElement)\n\n\t\t// Step 13. The inner loop. Find the lastNode to reparent.\n\t\tlastNode := furthestBlock\n\t\tnode := furthestBlock\n\t\tx := p.oe.index(node)\n\t\t// Steps 13.1-13.2\n\t\tfor j := 0; j < 3; j++ {\n\t\t\t// Step 13.3.\n\t\t\tx--\n\t\t\tnode = p.oe[x]\n\t\t\t// Step 13.4 - 13.5.\n\t\t\tif p.afe.index(node) == -1 {\n\t\t\t\tp.oe.remove(node)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Step 13.6.\n\t\t\tif node == formattingElement {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\t// Step 13.7.\n\t\t\tclone := node.clone()\n\t\t\tp.afe[p.afe.index(node)] = clone\n\t\t\tp.oe[p.oe.index(node)] = clone\n\t\t\tnode = clone\n\t\t\t// Step 13.8.\n\t\t\tif lastNode == furthestBlock {\n\t\t\t\tbookmark = p.afe.index(node) + 1\n\t\t\t}\n\t\t\t// Step 13.9.\n\t\t\tif lastNode.Parent != nil {\n\t\t\t\tlastNode.Parent.RemoveChild(lastNode)\n\t\t\t}\n\t\t\tnode.AppendChild(lastNode)\n\t\t\t// Step 13.10.\n\t\t\tlastNode = node\n\t\t}\n\n\t\t// Step 14. Reparent lastNode to the common ancestor,\n\t\t// or for misnested table nodes, to the foster parent.\n\t\tif lastNode.Parent != nil {\n\t\t\tlastNode.Parent.RemoveChild(lastNode)\n\t\t}\n\t\tswitch commonAncestor.DataAtom {\n\t\tcase a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:\n\t\t\tp.fosterParent(lastNode)\n\t\tdefault:\n\t\t\tcommonAncestor.AppendChild(lastNode)\n\t\t}\n\n\t\t// Steps 15-17. Reparent nodes from the furthest block's children\n\t\t// to a clone of the formatting element.\n\t\tclone := formattingElement.clone()\n\t\treparentChildren(clone, furthestBlock)\n\t\tfurthestBlock.AppendChild(clone)\n\n\t\t// Step 18. Fix up the list of active formatting elements.\n\t\tif oldLoc := p.afe.index(formattingElement); oldLoc != -1 && oldLoc < bookmark {\n\t\t\t// Move the bookmark with the rest of the list.\n\t\t\tbookmark--\n\t\t}\n\t\tp.afe.remove(formattingElement)\n\t\tp.afe.insert(bookmark, clone)\n\n\t\t// Step 19. Fix up the stack of open elements.\n\t\tp.oe.remove(formattingElement)\n\t\tp.oe.insert(p.oe.index(furthestBlock)+1, clone)\n\t}\n}\n\n// inBodyEndTagOther performs the \"any other end tag\" algorithm for inBodyIM.\n// \"Any other end tag\" handling from 12.2.5.5 The rules for parsing tokens in foreign content\n// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inforeign\nfunc (p *parser) inBodyEndTagOther(tagAtom a.Atom) {\n\tfor i := len(p.oe) - 1; i >= 0; i-- {\n\t\tif p.oe[i].DataAtom == tagAtom {\n\t\t\tp.oe = p.oe[:i]\n\t\t\tbreak\n\t\t}\n\t\tif isSpecialElement(p.oe[i]) {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\n// Section 12.2.5.4.8.\nfunc textIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase ErrorToken:\n\t\tp.oe.pop()\n\tcase TextToken:\n\t\td := p.tok.Data\n\t\tif n := p.oe.top(); n.DataAtom == a.Textarea && n.FirstChild == nil {\n\t\t\t// Ignore a newline at the start of a <textarea> block.\n\t\t\tif d != \"\" && d[0] == '\\r' {\n\t\t\t\td = d[1:]\n\t\t\t}\n\t\t\tif d != \"\" && d[0] == '\\n' {\n\t\t\t\td = d[1:]\n\t\t\t}\n\t\t}\n\t\tif d == \"\" {\n\t\t\treturn true\n\t\t}\n\t\tp.addText(d)\n\t\treturn true\n\tcase EndTagToken:\n\t\tp.oe.pop()\n\t}\n\tp.im = p.originalIM\n\tp.originalIM = nil\n\treturn p.tok.Type == EndTagToken\n}\n\n// Section 12.2.5.4.9.\nfunc inTableIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase ErrorToken:\n\t\t// Stop parsing.\n\t\treturn true\n\tcase TextToken:\n\t\tp.tok.Data = strings.Replace(p.tok.Data, \"\\x00\", \"\", -1)\n\t\tswitch p.oe.top().DataAtom {\n\t\tcase a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:\n\t\t\tif strings.Trim(p.tok.Data, whitespace) == \"\" {\n\t\t\t\tp.addText(p.tok.Data)\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\tcase StartTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Caption:\n\t\t\tp.clearStackToContext(tableScope)\n\t\t\tp.afe = append(p.afe, &scopeMarker)\n\t\t\tp.addElement()\n\t\t\tp.im = inCaptionIM\n\t\t\treturn true\n\t\tcase a.Colgroup:\n\t\t\tp.clearStackToContext(tableScope)\n\t\t\tp.addElement()\n\t\t\tp.im = inColumnGroupIM\n\t\t\treturn true\n\t\tcase a.Col:\n\t\t\tp.parseImpliedToken(StartTagToken, a.Colgroup, a.Colgroup.String())\n\t\t\treturn false\n\t\tcase a.Tbody, a.Tfoot, a.Thead:\n\t\t\tp.clearStackToContext(tableScope)\n\t\t\tp.addElement()\n\t\t\tp.im = inTableBodyIM\n\t\t\treturn true\n\t\tcase a.Td, a.Th, a.Tr:\n\t\t\tp.parseImpliedToken(StartTagToken, a.Tbody, a.Tbody.String())\n\t\t\treturn false\n\t\tcase a.Table:\n\t\t\tif p.popUntil(tableScope, a.Table) {\n\t\t\t\tp.resetInsertionMode()\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\tcase a.Style, a.Script:\n\t\t\treturn inHeadIM(p)\n\t\tcase a.Input:\n\t\t\tfor _, t := range p.tok.Attr {\n\t\t\t\tif t.Key == \"type\" && strings.ToLower(t.Val) == \"hidden\" {\n\t\t\t\t\tp.addElement()\n\t\t\t\t\tp.oe.pop()\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Otherwise drop down to the default action.\n\t\tcase a.Form:\n\t\t\tif p.form != nil {\n\t\t\t\t// Ignore the token.\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tp.addElement()\n\t\t\tp.form = p.oe.pop()\n\t\tcase a.Select:\n\t\t\tp.reconstructActiveFormattingElements()\n\t\t\tswitch p.top().DataAtom {\n\t\t\tcase a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:\n\t\t\t\tp.fosterParenting = true\n\t\t\t}\n\t\t\tp.addElement()\n\t\t\tp.fosterParenting = false\n\t\t\tp.framesetOK = false\n\t\t\tp.im = inSelectInTableIM\n\t\t\treturn true\n\t\t}\n\tcase EndTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Table:\n\t\t\tif p.popUntil(tableScope, a.Table) {\n\t\t\t\tp.resetInsertionMode()\n\t\t\t\treturn true\n\t\t\t}\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\tcase a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\t}\n\tcase CommentToken:\n\t\tp.addChild(&Node{\n\t\t\tType: CommentNode,\n\t\t\tData: p.tok.Data,\n\t\t})\n\t\treturn true\n\tcase DoctypeToken:\n\t\t// Ignore the token.\n\t\treturn true\n\t}\n\n\tp.fosterParenting = true\n\tdefer func() { p.fosterParenting = false }()\n\n\treturn inBodyIM(p)\n}\n\n// Section 12.2.5.4.11.\nfunc inCaptionIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase StartTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Caption, a.Col, a.Colgroup, a.Tbody, a.Td, a.Tfoot, a.Thead, a.Tr:\n\t\t\tif p.popUntil(tableScope, a.Caption) {\n\t\t\t\tp.clearActiveFormattingElements()\n\t\t\t\tp.im = inTableIM\n\t\t\t\treturn false\n\t\t\t} else {\n\t\t\t\t// Ignore the token.\n\t\t\t\treturn true\n\t\t\t}\n\t\tcase a.Select:\n\t\t\tp.reconstructActiveFormattingElements()\n\t\t\tp.addElement()\n\t\t\tp.framesetOK = false\n\t\t\tp.im = inSelectInTableIM\n\t\t\treturn true\n\t\t}\n\tcase EndTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Caption:\n\t\t\tif p.popUntil(tableScope, a.Caption) {\n\t\t\t\tp.clearActiveFormattingElements()\n\t\t\t\tp.im = inTableIM\n\t\t\t}\n\t\t\treturn true\n\t\tcase a.Table:\n\t\t\tif p.popUntil(tableScope, a.Caption) {\n\t\t\t\tp.clearActiveFormattingElements()\n\t\t\t\tp.im = inTableIM\n\t\t\t\treturn false\n\t\t\t} else {\n\t\t\t\t// Ignore the token.\n\t\t\t\treturn true\n\t\t\t}\n\t\tcase a.Body, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\t}\n\t}\n\treturn inBodyIM(p)\n}\n\n// Section 12.2.5.4.12.\nfunc inColumnGroupIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase TextToken:\n\t\ts := strings.TrimLeft(p.tok.Data, whitespace)\n\t\tif len(s) < len(p.tok.Data) {\n\t\t\t// Add the initial whitespace to the current node.\n\t\t\tp.addText(p.tok.Data[:len(p.tok.Data)-len(s)])\n\t\t\tif s == \"\" {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tp.tok.Data = s\n\t\t}\n\tcase CommentToken:\n\t\tp.addChild(&Node{\n\t\t\tType: CommentNode,\n\t\t\tData: p.tok.Data,\n\t\t})\n\t\treturn true\n\tcase DoctypeToken:\n\t\t// Ignore the token.\n\t\treturn true\n\tcase StartTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Html:\n\t\t\treturn inBodyIM(p)\n\t\tcase a.Col:\n\t\t\tp.addElement()\n\t\t\tp.oe.pop()\n\t\t\tp.acknowledgeSelfClosingTag()\n\t\t\treturn true\n\t\t}\n\tcase EndTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Colgroup:\n\t\t\tif p.oe.top().DataAtom != a.Html {\n\t\t\t\tp.oe.pop()\n\t\t\t\tp.im = inTableIM\n\t\t\t}\n\t\t\treturn true\n\t\tcase a.Col:\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\t}\n\t}\n\tif p.oe.top().DataAtom != a.Html {\n\t\tp.oe.pop()\n\t\tp.im = inTableIM\n\t\treturn false\n\t}\n\treturn true\n}\n\n// Section 12.2.5.4.13.\nfunc inTableBodyIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase StartTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Tr:\n\t\t\tp.clearStackToContext(tableBodyScope)\n\t\t\tp.addElement()\n\t\t\tp.im = inRowIM\n\t\t\treturn true\n\t\tcase a.Td, a.Th:\n\t\t\tp.parseImpliedToken(StartTagToken, a.Tr, a.Tr.String())\n\t\t\treturn false\n\t\tcase a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead:\n\t\t\tif p.popUntil(tableScope, a.Tbody, a.Thead, a.Tfoot) {\n\t\t\t\tp.im = inTableIM\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\t}\n\tcase EndTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Tbody, a.Tfoot, a.Thead:\n\t\t\tif p.elementInScope(tableScope, p.tok.DataAtom) {\n\t\t\t\tp.clearStackToContext(tableBodyScope)\n\t\t\t\tp.oe.pop()\n\t\t\t\tp.im = inTableIM\n\t\t\t}\n\t\t\treturn true\n\t\tcase a.Table:\n\t\t\tif p.popUntil(tableScope, a.Tbody, a.Thead, a.Tfoot) {\n\t\t\t\tp.im = inTableIM\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\tcase a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Td, a.Th, a.Tr:\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\t}\n\tcase CommentToken:\n\t\tp.addChild(&Node{\n\t\t\tType: CommentNode,\n\t\t\tData: p.tok.Data,\n\t\t})\n\t\treturn true\n\t}\n\n\treturn inTableIM(p)\n}\n\n// Section 12.2.5.4.14.\nfunc inRowIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase StartTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Td, a.Th:\n\t\t\tp.clearStackToContext(tableRowScope)\n\t\t\tp.addElement()\n\t\t\tp.afe = append(p.afe, &scopeMarker)\n\t\t\tp.im = inCellIM\n\t\t\treturn true\n\t\tcase a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead, a.Tr:\n\t\t\tif p.popUntil(tableScope, a.Tr) {\n\t\t\t\tp.im = inTableBodyIM\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\t}\n\tcase EndTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Tr:\n\t\t\tif p.popUntil(tableScope, a.Tr) {\n\t\t\t\tp.im = inTableBodyIM\n\t\t\t\treturn true\n\t\t\t}\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\tcase a.Table:\n\t\t\tif p.popUntil(tableScope, a.Tr) {\n\t\t\t\tp.im = inTableBodyIM\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\tcase a.Tbody, a.Tfoot, a.Thead:\n\t\t\tif p.elementInScope(tableScope, p.tok.DataAtom) {\n\t\t\t\tp.parseImpliedToken(EndTagToken, a.Tr, a.Tr.String())\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\tcase a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Td, a.Th:\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn inTableIM(p)\n}\n\n// Section 12.2.5.4.15.\nfunc inCellIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase StartTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Caption, a.Col, a.Colgroup, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:\n\t\t\tif p.popUntil(tableScope, a.Td, a.Th) {\n\t\t\t\t// Close the cell and reprocess.\n\t\t\t\tp.clearActiveFormattingElements()\n\t\t\t\tp.im = inRowIM\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\tcase a.Select:\n\t\t\tp.reconstructActiveFormattingElements()\n\t\t\tp.addElement()\n\t\t\tp.framesetOK = false\n\t\t\tp.im = inSelectInTableIM\n\t\t\treturn true\n\t\t}\n\tcase EndTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Td, a.Th:\n\t\t\tif !p.popUntil(tableScope, p.tok.DataAtom) {\n\t\t\t\t// Ignore the token.\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tp.clearActiveFormattingElements()\n\t\t\tp.im = inRowIM\n\t\t\treturn true\n\t\tcase a.Body, a.Caption, a.Col, a.Colgroup, a.Html:\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\tcase a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:\n\t\t\tif !p.elementInScope(tableScope, p.tok.DataAtom) {\n\t\t\t\t// Ignore the token.\n\t\t\t\treturn true\n\t\t\t}\n\t\t\t// Close the cell and reprocess.\n\t\t\tp.popUntil(tableScope, a.Td, a.Th)\n\t\t\tp.clearActiveFormattingElements()\n\t\t\tp.im = inRowIM\n\t\t\treturn false\n\t\t}\n\t}\n\treturn inBodyIM(p)\n}\n\n// Section 12.2.5.4.16.\nfunc inSelectIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase ErrorToken:\n\t\t// Stop parsing.\n\t\treturn true\n\tcase TextToken:\n\t\tp.addText(strings.Replace(p.tok.Data, \"\\x00\", \"\", -1))\n\tcase StartTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Html:\n\t\t\treturn inBodyIM(p)\n\t\tcase a.Option:\n\t\t\tif p.top().DataAtom == a.Option {\n\t\t\t\tp.oe.pop()\n\t\t\t}\n\t\t\tp.addElement()\n\t\tcase a.Optgroup:\n\t\t\tif p.top().DataAtom == a.Option {\n\t\t\t\tp.oe.pop()\n\t\t\t}\n\t\t\tif p.top().DataAtom == a.Optgroup {\n\t\t\t\tp.oe.pop()\n\t\t\t}\n\t\t\tp.addElement()\n\t\tcase a.Select:\n\t\t\tp.tok.Type = EndTagToken\n\t\t\treturn false\n\t\tcase a.Input, a.Keygen, a.Textarea:\n\t\t\tif p.elementInScope(selectScope, a.Select) {\n\t\t\t\tp.parseImpliedToken(EndTagToken, a.Select, a.Select.String())\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// In order to properly ignore <textarea>, we need to change the tokenizer mode.\n\t\t\tp.tokenizer.NextIsNotRawText()\n\t\t\t// Ignore the token.\n\t\t\treturn true\n\t\tcase a.Script:\n\t\t\treturn inHeadIM(p)\n\t\t}\n\tcase EndTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Option:\n\t\t\tif p.top().DataAtom == a.Option {\n\t\t\t\tp.oe.pop()\n\t\t\t}\n\t\tcase a.Optgroup:\n\t\t\ti := len(p.oe) - 1\n\t\t\tif p.oe[i].DataAtom == a.Option {\n\t\t\t\ti--\n\t\t\t}\n\t\t\tif p.oe[i].DataAtom == a.Optgroup {\n\t\t\t\tp.oe = p.oe[:i]\n\t\t\t}\n\t\tcase a.Select:\n\t\t\tif p.popUntil(selectScope, a.Select) {\n\t\t\t\tp.resetInsertionMode()\n\t\t\t}\n\t\t}\n\tcase CommentToken:\n\t\tp.addChild(&Node{\n\t\t\tType: CommentNode,\n\t\t\tData: p.tok.Data,\n\t\t})\n\tcase DoctypeToken:\n\t\t// Ignore the token.\n\t\treturn true\n\t}\n\n\treturn true\n}\n\n// Section 12.2.5.4.17.\nfunc inSelectInTableIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase StartTagToken, EndTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Caption, a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr, a.Td, a.Th:\n\t\t\tif p.tok.Type == StartTagToken || p.elementInScope(tableScope, p.tok.DataAtom) {\n\t\t\t\tp.parseImpliedToken(EndTagToken, a.Select, a.Select.String())\n\t\t\t\treturn false\n\t\t\t} else {\n\t\t\t\t// Ignore the token.\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t}\n\treturn inSelectIM(p)\n}\n\n// Section 12.2.5.4.18.\nfunc afterBodyIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase ErrorToken:\n\t\t// Stop parsing.\n\t\treturn true\n\tcase TextToken:\n\t\ts := strings.TrimLeft(p.tok.Data, whitespace)\n\t\tif len(s) == 0 {\n\t\t\t// It was all whitespace.\n\t\t\treturn inBodyIM(p)\n\t\t}\n\tcase StartTagToken:\n\t\tif p.tok.DataAtom == a.Html {\n\t\t\treturn inBodyIM(p)\n\t\t}\n\tcase EndTagToken:\n\t\tif p.tok.DataAtom == a.Html {\n\t\t\tif !p.fragment {\n\t\t\t\tp.im = afterAfterBodyIM\n\t\t\t}\n\t\t\treturn true\n\t\t}\n\tcase CommentToken:\n\t\t// The comment is attached to the <html> element.\n\t\tif len(p.oe) < 1 || p.oe[0].DataAtom != a.Html {\n\t\t\tpanic(\"html: bad parser state: <html> element not found, in the after-body insertion mode\")\n\t\t}\n\t\tp.oe[0].AppendChild(&Node{\n\t\t\tType: CommentNode,\n\t\t\tData: p.tok.Data,\n\t\t})\n\t\treturn true\n\t}\n\tp.im = inBodyIM\n\treturn false\n}\n\n// Section 12.2.5.4.19.\nfunc inFramesetIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase CommentToken:\n\t\tp.addChild(&Node{\n\t\t\tType: CommentNode,\n\t\t\tData: p.tok.Data,\n\t\t})\n\tcase TextToken:\n\t\t// Ignore all text but whitespace.\n\t\ts := strings.Map(func(c rune) rune {\n\t\t\tswitch c {\n\t\t\tcase ' ', '\\t', '\\n', '\\f', '\\r':\n\t\t\t\treturn c\n\t\t\t}\n\t\t\treturn -1\n\t\t}, p.tok.Data)\n\t\tif s != \"\" {\n\t\t\tp.addText(s)\n\t\t}\n\tcase StartTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Html:\n\t\t\treturn inBodyIM(p)\n\t\tcase a.Frameset:\n\t\t\tp.addElement()\n\t\tcase a.Frame:\n\t\t\tp.addElement()\n\t\t\tp.oe.pop()\n\t\t\tp.acknowledgeSelfClosingTag()\n\t\tcase a.Noframes:\n\t\t\treturn inHeadIM(p)\n\t\t}\n\tcase EndTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Frameset:\n\t\t\tif p.oe.top().DataAtom != a.Html {\n\t\t\t\tp.oe.pop()\n\t\t\t\tif p.oe.top().DataAtom != a.Frameset {\n\t\t\t\t\tp.im = afterFramesetIM\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tdefault:\n\t\t// Ignore the token.\n\t}\n\treturn true\n}\n\n// Section 12.2.5.4.20.\nfunc afterFramesetIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase CommentToken:\n\t\tp.addChild(&Node{\n\t\t\tType: CommentNode,\n\t\t\tData: p.tok.Data,\n\t\t})\n\tcase TextToken:\n\t\t// Ignore all text but whitespace.\n\t\ts := strings.Map(func(c rune) rune {\n\t\t\tswitch c {\n\t\t\tcase ' ', '\\t', '\\n', '\\f', '\\r':\n\t\t\t\treturn c\n\t\t\t}\n\t\t\treturn -1\n\t\t}, p.tok.Data)\n\t\tif s != \"\" {\n\t\t\tp.addText(s)\n\t\t}\n\tcase StartTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Html:\n\t\t\treturn inBodyIM(p)\n\t\tcase a.Noframes:\n\t\t\treturn inHeadIM(p)\n\t\t}\n\tcase EndTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Html:\n\t\t\tp.im = afterAfterFramesetIM\n\t\t\treturn true\n\t\t}\n\tdefault:\n\t\t// Ignore the token.\n\t}\n\treturn true\n}\n\n// Section 12.2.5.4.21.\nfunc afterAfterBodyIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase ErrorToken:\n\t\t// Stop parsing.\n\t\treturn true\n\tcase TextToken:\n\t\ts := strings.TrimLeft(p.tok.Data, whitespace)\n\t\tif len(s) == 0 {\n\t\t\t// It was all whitespace.\n\t\t\treturn inBodyIM(p)\n\t\t}\n\tcase StartTagToken:\n\t\tif p.tok.DataAtom == a.Html {\n\t\t\treturn inBodyIM(p)\n\t\t}\n\tcase CommentToken:\n\t\tp.doc.AppendChild(&Node{\n\t\t\tType: CommentNode,\n\t\t\tData: p.tok.Data,\n\t\t})\n\t\treturn true\n\tcase DoctypeToken:\n\t\treturn inBodyIM(p)\n\t}\n\tp.im = inBodyIM\n\treturn false\n}\n\n// Section 12.2.5.4.22.\nfunc afterAfterFramesetIM(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase CommentToken:\n\t\tp.doc.AppendChild(&Node{\n\t\t\tType: CommentNode,\n\t\t\tData: p.tok.Data,\n\t\t})\n\tcase TextToken:\n\t\t// Ignore all text but whitespace.\n\t\ts := strings.Map(func(c rune) rune {\n\t\t\tswitch c {\n\t\t\tcase ' ', '\\t', '\\n', '\\f', '\\r':\n\t\t\t\treturn c\n\t\t\t}\n\t\t\treturn -1\n\t\t}, p.tok.Data)\n\t\tif s != \"\" {\n\t\t\tp.tok.Data = s\n\t\t\treturn inBodyIM(p)\n\t\t}\n\tcase StartTagToken:\n\t\tswitch p.tok.DataAtom {\n\t\tcase a.Html:\n\t\t\treturn inBodyIM(p)\n\t\tcase a.Noframes:\n\t\t\treturn inHeadIM(p)\n\t\t}\n\tcase DoctypeToken:\n\t\treturn inBodyIM(p)\n\tdefault:\n\t\t// Ignore the token.\n\t}\n\treturn true\n}\n\nconst whitespaceOrNUL = whitespace + \"\\x00\"\n\n// Section 12.2.5.5.\nfunc parseForeignContent(p *parser) bool {\n\tswitch p.tok.Type {\n\tcase TextToken:\n\t\tif p.framesetOK {\n\t\t\tp.framesetOK = strings.TrimLeft(p.tok.Data, whitespaceOrNUL) == \"\"\n\t\t}\n\t\tp.tok.Data = strings.Replace(p.tok.Data, \"\\x00\", \"\\ufffd\", -1)\n\t\tp.addText(p.tok.Data)\n\tcase CommentToken:\n\t\tp.addChild(&Node{\n\t\t\tType: CommentNode,\n\t\t\tData: p.tok.Data,\n\t\t})\n\tcase StartTagToken:\n\t\tb := breakout[p.tok.Data]\n\t\tif p.tok.DataAtom == a.Font {\n\t\tloop:\n\t\t\tfor _, attr := range p.tok.Attr {\n\t\t\t\tswitch attr.Key {\n\t\t\t\tcase \"color\", \"face\", \"size\":\n\t\t\t\t\tb = true\n\t\t\t\t\tbreak loop\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif b {\n\t\t\tfor i := len(p.oe) - 1; i >= 0; i-- {\n\t\t\t\tn := p.oe[i]\n\t\t\t\tif n.Namespace == \"\" || htmlIntegrationPoint(n) || mathMLTextIntegrationPoint(n) {\n\t\t\t\t\tp.oe = p.oe[:i+1]\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\tswitch p.top().Namespace {\n\t\tcase \"math\":\n\t\t\tadjustAttributeNames(p.tok.Attr, mathMLAttributeAdjustments)\n\t\tcase \"svg\":\n\t\t\t// Adjust SVG tag names. The tokenizer lower-cases tag names, but\n\t\t\t// SVG wants e.g. \"foreignObject\" with a capital second \"O\".\n\t\t\tif x := svgTagNameAdjustments[p.tok.Data]; x != \"\" {\n\t\t\t\tp.tok.DataAtom = a.Lookup([]byte(x))\n\t\t\t\tp.tok.Data = x\n\t\t\t}\n\t\t\tadjustAttributeNames(p.tok.Attr, svgAttributeAdjustments)\n\t\tdefault:\n\t\t\tpanic(\"html: bad parser state: unexpected namespace\")\n\t\t}\n\t\tadjustForeignAttributes(p.tok.Attr)\n\t\tnamespace := p.top().Namespace\n\t\tp.addElement()\n\t\tp.top().Namespace = namespace\n\t\tif namespace != \"\" {\n\t\t\t// Don't let the tokenizer go into raw text mode in foreign content\n\t\t\t// (e.g. in an SVG <title> tag).\n\t\t\tp.tokenizer.NextIsNotRawText()\n\t\t}\n\t\tif p.hasSelfClosingToken {\n\t\t\tp.oe.pop()\n\t\t\tp.acknowledgeSelfClosingTag()\n\t\t}\n\tcase EndTagToken:\n\t\tfor i := len(p.oe) - 1; i >= 0; i-- {\n\t\t\tif p.oe[i].Namespace == \"\" {\n\t\t\t\treturn p.im(p)\n\t\t\t}\n\t\t\tif strings.EqualFold(p.oe[i].Data, p.tok.Data) {\n\t\t\t\tp.oe = p.oe[:i]\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\treturn true\n\tdefault:\n\t\t// Ignore the token.\n\t}\n\treturn true\n}\n\n// Section 12.2.5.\nfunc (p *parser) inForeignContent() bool {\n\tif len(p.oe) == 0 {\n\t\treturn false\n\t}\n\tn := p.oe[len(p.oe)-1]\n\tif n.Namespace == \"\" {\n\t\treturn false\n\t}\n\tif mathMLTextIntegrationPoint(n) {\n\t\tif p.tok.Type == StartTagToken && p.tok.DataAtom != a.Mglyph && p.tok.DataAtom != a.Malignmark {\n\t\t\treturn false\n\t\t}\n\t\tif p.tok.Type == TextToken {\n\t\t\treturn false\n\t\t}\n\t}\n\tif n.Namespace == \"math\" && n.DataAtom == a.AnnotationXml && p.tok.Type == StartTagToken && p.tok.DataAtom == a.Svg {\n\t\treturn false\n\t}\n\tif htmlIntegrationPoint(n) && (p.tok.Type == StartTagToken || p.tok.Type == TextToken) {\n\t\treturn false\n\t}\n\tif p.tok.Type == ErrorToken {\n\t\treturn false\n\t}\n\treturn true\n}\n\n// parseImpliedToken parses a token as though it had appeared in the parser's\n// input.\nfunc (p *parser) parseImpliedToken(t TokenType, dataAtom a.Atom, data string) {\n\trealToken, selfClosing := p.tok, p.hasSelfClosingToken\n\tp.tok = Token{\n\t\tType:     t,\n\t\tDataAtom: dataAtom,\n\t\tData:     data,\n\t}\n\tp.hasSelfClosingToken = false\n\tp.parseCurrentToken()\n\tp.tok, p.hasSelfClosingToken = realToken, selfClosing\n}\n\n// parseCurrentToken runs the current token through the parsing routines\n// until it is consumed.\nfunc (p *parser) parseCurrentToken() {\n\tif p.tok.Type == SelfClosingTagToken {\n\t\tp.hasSelfClosingToken = true\n\t\tp.tok.Type = StartTagToken\n\t}\n\n\tconsumed := false\n\tfor !consumed {\n\t\tif p.inForeignContent() {\n\t\t\tconsumed = parseForeignContent(p)\n\t\t} else {\n\t\t\tconsumed = p.im(p)\n\t\t}\n\t}\n\n\tif p.hasSelfClosingToken {\n\t\t// This is a parse error, but ignore it.\n\t\tp.hasSelfClosingToken = false\n\t}\n}\n\nfunc (p *parser) parse() error {\n\t// Iterate until EOF. Any other error will cause an early return.\n\tvar err error\n\tfor err != io.EOF {\n\t\t// CDATA sections are allowed only in foreign content.\n\t\tn := p.oe.top()\n\t\tp.tokenizer.AllowCDATA(n != nil && n.Namespace != \"\")\n\t\t// Read and parse the next token.\n\t\tp.tokenizer.Next()\n\t\tp.tok = p.tokenizer.Token()\n\t\tif p.tok.Type == ErrorToken {\n\t\t\terr = p.tokenizer.Err()\n\t\t\tif err != nil && err != io.EOF {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tp.parseCurrentToken()\n\t}\n\treturn nil\n}\n\n// Parse returns the parse tree for the HTML from the given Reader.\n// The input is assumed to be UTF-8 encoded.\nfunc Parse(r io.Reader) (*Node, error) {\n\tp := &parser{\n\t\ttokenizer: NewTokenizer(r),\n\t\tdoc: &Node{\n\t\t\tType: DocumentNode,\n\t\t},\n\t\tscripting:  true,\n\t\tframesetOK: true,\n\t\tim:         initialIM,\n\t}\n\terr := p.parse()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn p.doc, nil\n}\n\n// ParseFragment parses a fragment of HTML and returns the nodes that were\n// found. If the fragment is the InnerHTML for an existing element, pass that\n// element in context.\nfunc ParseFragment(r io.Reader, context *Node) ([]*Node, error) {\n\tcontextTag := \"\"\n\tif context != nil {\n\t\tif context.Type != ElementNode {\n\t\t\treturn nil, errors.New(\"html: ParseFragment of non-element Node\")\n\t\t}\n\t\t// The next check isn't just context.DataAtom.String() == context.Data because\n\t\t// it is valid to pass an element whose tag isn't a known atom. For example,\n\t\t// DataAtom == 0 and Data = \"tagfromthefuture\" is perfectly consistent.\n\t\tif context.DataAtom != a.Lookup([]byte(context.Data)) {\n\t\t\treturn nil, fmt.Errorf(\"html: inconsistent Node: DataAtom=%q, Data=%q\", context.DataAtom, context.Data)\n\t\t}\n\t\tcontextTag = context.DataAtom.String()\n\t}\n\tp := &parser{\n\t\ttokenizer: NewTokenizerFragment(r, contextTag),\n\t\tdoc: &Node{\n\t\t\tType: DocumentNode,\n\t\t},\n\t\tscripting: true,\n\t\tfragment:  true,\n\t\tcontext:   context,\n\t}\n\n\troot := &Node{\n\t\tType:     ElementNode,\n\t\tDataAtom: a.Html,\n\t\tData:     a.Html.String(),\n\t}\n\tp.doc.AppendChild(root)\n\tp.oe = nodeStack{root}\n\tp.resetInsertionMode()\n\n\tfor n := context; n != nil; n = n.Parent {\n\t\tif n.Type == ElementNode && n.DataAtom == a.Form {\n\t\t\tp.form = n\n\t\t\tbreak\n\t\t}\n\t}\n\n\terr := p.parse()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tparent := p.doc\n\tif context != nil {\n\t\tparent = root\n\t}\n\n\tvar result []*Node\n\tfor c := parent.FirstChild; c != nil; {\n\t\tnext := c.NextSibling\n\t\tparent.RemoveChild(c)\n\t\tresult = append(result, c)\n\t\tc = next\n\t}\n\treturn result, nil\n}\n"
  }
]