├── .gitignore ├── .goreleaser.yml ├── .tool-versions ├── .vscode └── launch.json ├── CHANGELOG.md ├── Development.md ├── Dockerfile ├── LICENSE ├── README.md ├── cmd └── scip-go │ ├── main.go │ └── paths.go ├── dev └── publish-release.sh ├── go.mod ├── go.sum ├── internal ├── command │ └── command.go ├── config │ └── config.go ├── document │ └── document.go ├── funk │ └── funk.go ├── git │ ├── infer_module_version.go │ ├── infer_repo.go │ ├── infer_repo_test.go │ └── toplevel.go ├── handler │ └── handler.go ├── implementations │ └── implementations.go ├── index │ ├── package_ident.go │ ├── package_ident_test.go │ ├── scip.go │ ├── scip_test.go │ └── version.txt ├── loader │ ├── loader.go │ ├── loader_test.go │ └── stdlib.go ├── lookup │ └── lookup.go ├── modules │ └── modules.go ├── newtypes │ └── newtypes.go ├── output │ ├── duration.go │ ├── duration_test.go │ └── output.go ├── parallel │ ├── parallel.go │ └── parallel_test.go ├── symbols │ └── symbols.go ├── testdata │ └── snapshots │ │ ├── input │ │ ├── alias │ │ │ └── main.go │ │ ├── embedded │ │ │ ├── embedded.go │ │ │ ├── go.mod │ │ │ ├── internal │ │ │ │ └── nested.go │ │ │ ├── nested.go │ │ │ └── something.go │ │ ├── generallyeric │ │ │ ├── generallyeric.go │ │ │ ├── go.mod │ │ │ ├── go.sum │ │ │ ├── new_operators.go │ │ │ └── person.go │ │ ├── impls │ │ │ ├── go.mod │ │ │ ├── impls.go │ │ │ └── remote_impls.go │ │ ├── initial │ │ │ ├── builtin_types.go │ │ │ ├── child_symbols.go │ │ │ ├── func_declarations.go │ │ │ ├── go.mod │ │ │ ├── methods_and_receivers.go │ │ │ ├── package_definition.go │ │ │ ├── rangefunc.go │ │ │ ├── toplevel_decls.go │ │ │ ├── type_declarations.go │ │ │ └── type_hovers.go │ │ ├── inlinestruct │ │ │ ├── go.mod │ │ │ ├── inlinestruct.go │ │ │ ├── inlinestruct_func.go │ │ │ ├── inlinestruct_genericindex.go │ │ │ ├── inlinestruct_interface.go │ │ │ ├── inlinestruct_map.go │ │ │ └── inlinestruct_multivar.go │ │ ├── package-documentation │ │ │ ├── primary.go │ │ │ └── secondary.go │ │ ├── replace-directives │ │ │ ├── go.mod │ │ │ ├── go.sum │ │ │ └── replace_directives.go │ │ ├── sharedtestmodule │ │ │ ├── cmd │ │ │ │ └── gitserver │ │ │ │ │ └── server │ │ │ │ │ ├── cleanup.go │ │ │ │ │ ├── cleanup_test.go │ │ │ │ │ ├── server.go │ │ │ │ │ └── server_test.go │ │ │ └── go.mod │ │ ├── switches │ │ │ ├── go.mod │ │ │ └── switches.go │ │ ├── testdata │ │ │ ├── anonymous_structs.go │ │ │ ├── cmd │ │ │ │ └── minimal_main │ │ │ │ │ └── minimal_main.go │ │ │ ├── conflicting_test_symbols │ │ │ │ ├── sandbox_unsupported.go │ │ │ │ └── sandbox_unsupported_test.go │ │ │ ├── data.go │ │ │ ├── duplicate_path_id │ │ │ │ ├── main.go │ │ │ │ └── two.go │ │ │ ├── external_composite.go │ │ │ ├── go.mod │ │ │ ├── implementations.go │ │ │ ├── implementations_embedded.go │ │ │ ├── implementations_methods.go │ │ │ ├── implementations_remote.go │ │ │ ├── internal │ │ │ │ └── secret │ │ │ │ │ ├── doc.go │ │ │ │ │ └── secret.go │ │ │ ├── named_import.go │ │ │ ├── parallel.go │ │ │ ├── typealias.go │ │ │ └── typeswitch.go │ │ └── testspecial │ │ │ ├── foo.go │ │ │ ├── foo_other_test.go │ │ │ ├── foo_test.go │ │ │ └── go.mod │ │ └── output │ │ ├── alias │ │ └── main.go │ │ ├── embedded │ │ ├── embedded.go │ │ ├── internal │ │ │ └── nested.go │ │ ├── nested.go │ │ └── something.go │ │ ├── generallyeric │ │ ├── generallyeric.go │ │ ├── new_operators.go │ │ └── person.go │ │ ├── impls │ │ ├── impls.go │ │ └── remote_impls.go │ │ ├── initial │ │ ├── builtin_types.go │ │ ├── child_symbols.go │ │ ├── func_declarations.go │ │ ├── methods_and_receivers.go │ │ ├── package_definition.go │ │ ├── rangefunc.go │ │ ├── toplevel_decls.go │ │ ├── type_declarations.go │ │ └── type_hovers.go │ │ ├── inlinestruct │ │ ├── inlinestruct.go │ │ ├── inlinestruct_func.go │ │ ├── inlinestruct_genericindex.go │ │ ├── inlinestruct_interface.go │ │ ├── inlinestruct_map.go │ │ └── inlinestruct_multivar.go │ │ ├── package-documentation │ │ ├── primary.go │ │ └── secondary.go │ │ ├── replace-directives │ │ └── replace_directives.go │ │ ├── sharedtestmodule │ │ └── cmd │ │ │ └── gitserver │ │ │ └── server │ │ │ ├── cleanup.go │ │ │ ├── cleanup_test.go │ │ │ ├── server.go │ │ │ └── server_test.go │ │ ├── switches │ │ └── switches.go │ │ ├── testdata │ │ ├── anonymous_structs.go │ │ ├── cmd │ │ │ └── minimal_main │ │ │ │ └── minimal_main.go │ │ ├── conflicting_test_symbols │ │ │ └── sandbox_unsupported_test.go │ │ ├── data.go │ │ ├── duplicate_path_id │ │ │ ├── main.go │ │ │ └── two.go │ │ ├── external_composite.go │ │ ├── implementations.go │ │ ├── implementations_embedded.go │ │ ├── implementations_methods.go │ │ ├── implementations_remote.go │ │ ├── internal │ │ │ └── secret │ │ │ │ ├── doc.go │ │ │ │ └── secret.go │ │ ├── named_import.go │ │ ├── parallel.go │ │ ├── typealias.go │ │ └── typeswitch.go │ │ └── testspecial │ │ ├── foo.go │ │ ├── foo_other_test.go │ │ └── foo_test.go └── visitors │ ├── scope.go │ ├── visitor_file.go │ ├── visitor_func.go │ ├── visitor_type.go │ ├── visitor_var.go │ └── visitors.go └── scripts ├── dockerfile_checks.sh ├── gen_std_lib.sh └── sourcegraph_qa.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | 17 | /scip-go 18 | 19 | scratch/ 20 | .idea/ 21 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | project_name: scip-go 2 | version: 2 3 | 4 | dist: release 5 | 6 | env: 7 | - GO111MODULE=on 8 | - CGO_ENABLED=0 9 | 10 | before: 11 | hooks: 12 | - go mod download 13 | - go mod tidy 14 | 15 | builds: 16 | - 17 | main: ./cmd/scip-go/ 18 | binary: scip-go 19 | ldflags: 20 | - -X main.version={{.Version}} 21 | goos: 22 | - linux 23 | - windows 24 | - darwin 25 | goarch: 26 | - amd64 27 | - arm64 28 | 29 | archives: 30 | - id: tarball 31 | format: tar.gz 32 | 33 | dockers: 34 | - ids: 35 | - scip-go 36 | image_templates: 37 | - "sourcegraph/scip-go:{{ .Tag }}" 38 | - "sourcegraph/scip-go:v{{ .Major }}" 39 | - "sourcegraph/scip-go:v{{ .Major }}.{{ .Minor }}" 40 | - "sourcegraph/scip-go:latest" 41 | extra_files: 42 | - go.mod 43 | - go.sum 44 | - cmd 45 | - internal 46 | 47 | changelog: 48 | sort: asc 49 | filters: 50 | exclude: 51 | - '^docs:' 52 | - '^test:' 53 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | golang 1.24.0 2 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Run SCIP-GO", 6 | "type": "go", 7 | "request": "launch", 8 | "mode": "auto", 9 | "program": "cmd/scip-go", 10 | "cwd": "${input:path}", 11 | } 12 | ], 13 | "inputs": [ 14 | { 15 | "id": "path", 16 | "description": "Please enter the path to the project to index", 17 | "default": "", 18 | "type": "promptString" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # ChangeLog 2 | 3 | ## v0.1.24 4 | 5 | - Upgrades Dockerfile to use Go 1.24.3 (released May 6 2025). 6 | - Sets `GOTOOLCHAIN=auto` in Dockerfile by default, to allow 7 | for transparent toolchain upgrading if the network 8 | configuration allows it. 9 | 10 | ## v0.1.23 11 | 12 | - Upgrades Dockerfile to use Go 1.24.0 (released Feb 11 2025). 13 | (https://github.com/weightylarva/scip-go/pull/146) 14 | 15 | ## v0.1.22 16 | 17 | - Fixes a panic when using a custom GOPACKAGESDRIVER along 18 | with a build system other than the default Go build system 19 | (https://github.com/weightylarva/scip-go/pull/138) 20 | - Optionally allows passing package patterns to scip-go for 21 | only indexing a subset of packages. 22 | (https://github.com/weightylarva/scip-go/pull/139) 23 | - Upgrades Dockerfile to use Go 1.23.3 (released Oct 1 2024). 24 | (https://github.com/weightylarva/scip-go/pull/141) 25 | 26 | ## v0.1.21 27 | 28 | - Upgrades Dockerfile to use Go 1.23.2 (released Oct 1 2024). 29 | (https://github.com/weightylarva/scip-go/pull/136) 30 | 31 | ## v0.1.20 32 | 33 | - Fixes a bug which caused test files using the same package name 34 | as the main package to not be indexed. 35 | (https://github.com/weightylarva/scip-go/pull/134) 36 | 37 | ## v0.1.19 38 | 39 | - Upgrades Dockerfile to use Go 1.23.1 (released on Sept 05 2024). 40 | - Removes incorrect warning about missing ASTs for packages 41 | only containing test files. 42 | (https://github.com/weightylarva/scip-go/pull/129) 43 | 44 | ## v0.1.18 45 | 46 | - Adds more detailed logging for diagnosing hangs 47 | during indexing. 48 | (https://github.com/weightylarva/scip-go/pull/126) 49 | 50 | ## v0.1.17 51 | 52 | - Fixes panic due to alias types in v0.1.16. 53 | (https://github.com/weightylarva/scip-go/pull/121) 54 | 55 | ## v0.1.16 56 | 57 | NOTE: This release panics on alias types due to 58 | upstream Go bug [68877](https://github.com/golang/go/issues/68877); 59 | you can work around that by using `GODEBUG=gotypesalias=0`. 60 | 61 | - Updates the indexer and Dockerfile for Go 1.23.0 62 | (https://github.com/weightylarva/scip-go/pull/116) 63 | 64 | 65 | ## v0.1.15 66 | 67 | - Updates the Dockerfile to use Go 1.22.5. 68 | (https://github.com/weightylarva/scip-go/pull/111) 69 | 70 | ## v0.1.14 71 | 72 | - Fixes a bug with cross-repo navigation when depending 73 | on unpublished versions of libraries. 74 | (https://github.com/weightylarva/scip-go/pull/99) 75 | 76 | ## v0.1.13 77 | 78 | - Adds workaround for a panic triggerd by the presence of multiple 79 | field definitions with the same anonymous type. 80 | (https://github.com/weightylarva/scip-go/pull/96) 81 | 82 | ```go 83 | type T struct { 84 | A, B struct { B int } 85 | } 86 | ``` 87 | 88 | ## v0.1.12 89 | 90 | - Fixes the Dockerfile for the indexer. Due to a bug in the Dockerfile, 91 | the v0.1.11 release does not have any accompanying Docker image. 92 | (https://github.com/weightylarva/scip-go/pull/86) 93 | 94 | ## v0.1.11 95 | 96 | - Updates the indexer to build using Go 1.22.1. 97 | (https://github.com/weightylarva/scip-go/pull/81) 98 | 99 | ## v0.1.10 100 | 101 | - Updates the indexer to build using Go 1.21.5. 102 | (https://github.com/weightylarva/scip-go/pull/50) 103 | 104 | ## v0.1.9 105 | 106 | - Fixes a bug where the indexer would emit an empty SCIP index 107 | when hitting a panic. 108 | (https://github.com/weightylarva/scip-go/pull/62) 109 | 110 | ## v0.1.8 111 | 112 | - Fixed the version number emitted in SCIP indexes 113 | and printed by `scip-go --version`. 114 | (https://github.com/weightylarva/scip-go/pull/60) 115 | -------------------------------------------------------------------------------- /Development.md: -------------------------------------------------------------------------------- 1 | # Development docs 2 | 3 | ## Run tests 4 | 5 | Run all tests: 6 | 7 | ```bash 8 | go test ./... 9 | ``` 10 | 11 | Update snapshot tests: 12 | 13 | ```bash 14 | go test ./internal/index -update-snapshots 15 | ``` 16 | 17 | ## Cutting releases 18 | 19 | 1. Land a PR with the following changes: 20 | 21 | - A ChangeLog entry with `## vM.N.P` 22 | - Updated version in `internal/index/version.txt` 23 | 24 | 2. On the `main` branch, run the following: 25 | 26 | ```bash 27 | NEW_VERSION="M.N.P" ./dev/publish-release.sh 28 | ``` 29 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # When updating the version of the base container, please use the 2 | # SHA256 listed under 'Index digest' on Docker Hub, 3 | # not the 'Manifest digest'. 4 | # 5 | # This ensures that when pulling the container, Docker will detect 6 | # the platform and pull the correct image (if it exists) 7 | # 8 | # Alternate way of determining the Index digest using the docker CLI. 9 | # 10 | # $ docker buildx imagetools inspect golang:1.21.5-alpine 11 | # Name: docker.io/library/golang:1.21.5-alpine 12 | # MediaType: application/vnd.docker.distribution.manifest.list.v2+json 13 | # Digest: sha256:4db4aac30880b978cae5445dd4a706215249ad4f43d28bd7cdf7906e9be8dd6b 14 | # Manifests: 15 | # 16 | # And use this digest in FROM 17 | 18 | ARG base_sha=39d9e7d9c5d9c9e4baf0d8fff579f06d5032c0f4425cdec9e86732e8e4e374dc 19 | 20 | FROM golang:1.24.3@sha256:${base_sha} AS builder 21 | 22 | COPY . /sources 23 | WORKDIR /sources 24 | RUN go build -o scip-go ./cmd/scip-go 25 | 26 | # Keep in sync with builder image 27 | FROM golang:1.24.3@sha256:${base_sha} AS final 28 | 29 | COPY --from=builder /sources/scip-go /usr/bin/ 30 | ENV GOTOOLCHAIN=auto 31 | CMD ["scip-go"] 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # scip-go 2 | 3 | SCIP indexer for Golang. 4 | 5 | # Quick Start 6 | 7 | ## Installation 8 | 9 | This will build and install the latest version of `scip-go` 10 | 11 | ``` 12 | go install github.com/weightylarva/scip-go/cmd/scip-go@latest 13 | ``` 14 | 15 | You can confirm it's been installed by running: 16 | 17 | ``` 18 | scip-go --version 19 | ``` 20 | 21 | ## Indexing a Go project 22 | 23 | ### Standard `go.mod` project 24 | 25 | From the root of your project, you can run: 26 | 27 | ``` 28 | scip-go 29 | ``` 30 | 31 | If `scip-go` is unable to determine some project information, you may need to provide some command-line arguments. 32 | 33 | 34 | ``` 35 | scip-go --module-name=NAME --module-version=VERSION 36 | ``` 37 | 38 | If this doesn't solve the problem, check the rest of the available flags in: 39 | 40 | ``` 41 | scip-go --help 42 | ``` 43 | 44 | ### Other build systems 45 | 46 | The other build systems Buck/Bazel/Please/etc are supported via [Go Packages Driver Protocol](https://pkg.go.dev/golang.org/x/tools/go/packages#hdr-The_driver_protocol). 47 | 48 | 49 | Usage: 50 | ``` 51 | GOPACKAGESDRIVER=your_driver scip-go 52 | ``` 53 | 54 | Note: Due to the current protocol design cross-repo navigation will not work. 55 | 56 | ### Common Problems: 57 | 58 | - Unable to navigate to Go standard library. 59 | - To solve this, you may want to use the `--go-version=go1.X.Y` flag when indexing and then also index the go versions manually. 60 | - To index the Go standard library, you'll want to check out https://github.com/golang/go, checkout the tag you want, navigate to the `src/` directory, and then run: 61 | - `$ scip-go --go-version=go1.X.Y` and then upload that index to your local sourcegraph instance. 62 | - After you've done this, you should be able to navigate to the standard library. 63 | 64 | 65 | (NOTE: Projects without a `go.mod` may experience challenges indexing. See next section for details) 66 | 67 | ## Indexing without shelling to `go` binary 68 | 69 | `scip-go` by default uses a few different `go` commands from the command line to 70 | gain information about the project and module. To avoid running `go` directly 71 | (perhaps you have some other build system), you will need to supply the following args. 72 | 73 | ``` 74 | scip-go --module-name="" 75 | ``` 76 | 77 | NOTE: The rest of this isn't properly implemented yet. It's on the todo list for scip-go. 78 | 79 | ## Indexing in CI 80 | 81 | ``` 82 | # Install scip-go 83 | go install github.com/weightylarva/scip-go/cmd/scip-go@latest 84 | 85 | # Run scip-go 86 | scip-go 87 | 88 | # Upload index with any necessary tokens (shown here using GitHub workflow syntax) 89 | src code-intel upload -github-token='${{ secrets.GITHUB_TOKEN }}' -no-progress 90 | ``` 91 | 92 | ## Docker 93 | 94 | To build a self-contained Docker container with the indexer, use 95 | the following command: 96 | 97 | ```bash 98 | docker build -t scip-go:latest . 99 | ``` 100 | 101 | # Contributing 102 | 103 | Contributors should follow the [Sourcegraph Community Code of Conduct](https://handbook.sourcegraph.com/company-info-and-process/community/code_of_conduct/). 104 | -------------------------------------------------------------------------------- /cmd/scip-go/paths.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "strings" 7 | "sync" 8 | 9 | "github.com/weightylarva/scip-go/internal/git" 10 | ) 11 | 12 | var wd = sync.OnceValue(func() string { 13 | if wd, err := os.Getwd(); err == nil { 14 | return wd 15 | } 16 | 17 | return "" 18 | }) 19 | 20 | var toplevel = sync.OnceValue(func() string { 21 | if toplevel, err := git.TopLevel("."); err == nil { 22 | return toplevel 23 | } 24 | 25 | return "" 26 | }) 27 | 28 | func searchForGoMod(path, repositoryRoot string) string { 29 | for ; !strings.HasPrefix(path, repositoryRoot); path = filepath.Dir(path) { 30 | _, err := os.Stat(filepath.Join(path, "go.mod")) 31 | if err == nil { 32 | return rel(path) 33 | } 34 | 35 | if !os.IsNotExist(err) { 36 | // Actual FS error, stop 37 | break 38 | } 39 | 40 | if filepath.Dir(path) == path { 41 | // We just checked the root, prevent infinite loop 42 | break 43 | } 44 | } 45 | 46 | return "." 47 | } 48 | 49 | func rel(path string) string { 50 | relative, err := filepath.Rel(wd(), path) 51 | if err != nil { 52 | return "." 53 | } 54 | 55 | return relative 56 | } 57 | -------------------------------------------------------------------------------- /dev/publish-release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | { 6 | if [ -z "${NEW_VERSION:-}" ]; then 7 | echo "error: Missing value for environment variable NEW_VERSION" 8 | echo "hint: Invoke this script as NEW_VERSION=M.N.P ./dev/publish-release.sh" 9 | exit 1 10 | fi 11 | 12 | if ! grep -q "## v$NEW_VERSION" CHANGELOG.md; then 13 | echo "error: Missing CHANGELOG entry for v$NEW_VERSION" 14 | echo "note: CHANGELOG entries are required for publishing releases" 15 | exit 1 16 | fi 17 | 18 | VERSION_FILE_PATH="internal/index/version.txt" 19 | if ! grep -q "$NEW_VERSION" "$VERSION_FILE_PATH"; then 20 | echo "error: scip-go version in $VERSION_FILE_PATH doesn't match NEW_VERSION=$NEW_VERSION" 21 | exit 1 22 | fi 23 | 24 | if ! git diff --quiet; then 25 | echo "error: Found unstaged changes; aborting." 26 | exit 1 27 | fi 28 | 29 | if ! git diff --quiet --cached; then 30 | echo "error: Found staged-but-uncommitted changes; aborting." 31 | exit 1 32 | fi 33 | 34 | if ! git rev-parse --abbrev-ref HEAD | grep -q "main"; then 35 | echo "error: Releases should be published from main but HEAD is on a different branch" >&2 36 | exit 1 37 | fi 38 | } >&2 39 | 40 | TAG="v$NEW_VERSION" 41 | git tag "$TAG" 42 | git push origin "$TAG" 43 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/weightylarva/scip-go 2 | 3 | go 1.24.3 4 | 5 | require ( 6 | github.com/charmbracelet/log v0.4.0 7 | github.com/efritz/pentimento v0.0.0-20190429011147-ade47d831101 8 | github.com/sourcegraph/scip v0.4.1-0.20240819152428-9c4970218f55 9 | golang.org/x/tools v0.19.0 10 | golang.org/x/tools/go/vcs v0.1.0-deprecated 11 | ) 12 | 13 | require ( 14 | github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect 15 | github.com/Microsoft/go-winio v0.6.1 // indirect 16 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect 17 | github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect 18 | github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect 19 | github.com/bufbuild/connect-go v1.9.0 // indirect 20 | github.com/bufbuild/connect-opentelemetry-go v0.4.0 // indirect 21 | github.com/bufbuild/protocompile v0.5.1 // indirect 22 | github.com/charmbracelet/lipgloss v0.10.0 // indirect 23 | github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect 24 | github.com/docker/cli v24.0.4+incompatible // indirect 25 | github.com/docker/distribution v2.8.2+incompatible // indirect 26 | github.com/docker/docker v24.0.4+incompatible // indirect 27 | github.com/docker/docker-credential-helpers v0.8.0 // indirect 28 | github.com/docker/go-connections v0.4.0 // indirect 29 | github.com/docker/go-units v0.5.0 // indirect 30 | github.com/felixge/fgprof v0.9.3 // indirect 31 | github.com/go-chi/chi/v5 v5.0.10 // indirect 32 | github.com/go-logfmt/logfmt v0.6.0 // indirect 33 | github.com/go-logr/logr v1.2.4 // indirect 34 | github.com/go-logr/stdr v1.2.2 // indirect 35 | github.com/gofrs/uuid/v5 v5.0.0 // indirect 36 | github.com/gogo/protobuf v1.3.2 // indirect 37 | github.com/google/go-containerregistry v0.15.2 // indirect 38 | github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 // indirect 39 | github.com/lucasb-eyer/go-colorful v1.2.0 // indirect 40 | github.com/mattn/go-isatty v0.0.19 // indirect 41 | github.com/mattn/go-runewidth v0.0.15 // indirect 42 | github.com/mitchellh/go-homedir v1.1.0 // indirect 43 | github.com/moby/term v0.5.0 // indirect 44 | github.com/morikuni/aec v1.0.0 // indirect 45 | github.com/muesli/reflow v0.3.0 // indirect 46 | github.com/muesli/termenv v0.15.2 // indirect 47 | github.com/opencontainers/go-digest v1.0.0 // indirect 48 | github.com/opencontainers/image-spec v1.1.0-rc4 // indirect 49 | github.com/rivo/uniseg v0.4.7 // indirect 50 | github.com/rs/cors v1.9.0 // indirect 51 | github.com/sirupsen/logrus v1.9.3 // indirect 52 | github.com/tetratelabs/wazero v1.3.0 // indirect 53 | github.com/vbatts/tar-split v0.11.3 // indirect 54 | go.opentelemetry.io/otel v1.16.0 // indirect 55 | go.opentelemetry.io/otel/metric v1.16.0 // indirect 56 | go.opentelemetry.io/otel/sdk v1.16.0 // indirect 57 | go.opentelemetry.io/otel/trace v1.16.0 // indirect 58 | golang.org/x/sync v0.6.0 // indirect 59 | ) 60 | 61 | require ( 62 | github.com/Masterminds/semver v1.4.2 // indirect 63 | github.com/Masterminds/sprig v2.15.0+incompatible // indirect 64 | github.com/agnivade/levenshtein v1.1.1 65 | github.com/alecthomas/kingpin v2.2.6+incompatible 66 | github.com/aokoli/goutils v1.0.1 // indirect 67 | github.com/bufbuild/buf v1.25.0 // indirect 68 | github.com/cockroachdb/errors v1.8.9 // indirect 69 | github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f // indirect 70 | github.com/cockroachdb/redact v1.1.3 // indirect 71 | github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect 72 | github.com/davecgh/go-spew v1.1.1 // indirect 73 | github.com/envoyproxy/protoc-gen-validate v0.3.0-java // indirect 74 | github.com/getsentry/sentry-go v0.12.0 // indirect 75 | github.com/golang/protobuf v1.5.3 // indirect 76 | github.com/google/uuid v1.3.0 // indirect 77 | github.com/hexops/gotextdiff v1.0.3 // indirect 78 | github.com/huandu/xstrings v1.0.0 // indirect 79 | github.com/imdario/mergo v0.3.4 // indirect 80 | github.com/inconshreveable/mousetrap v1.1.0 // indirect 81 | github.com/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84 // indirect 82 | github.com/klauspost/compress v1.16.7 // indirect 83 | github.com/klauspost/pgzip v1.2.6 // indirect 84 | github.com/kr/pretty v0.3.1 // indirect 85 | github.com/kr/text v0.2.0 // indirect 86 | github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007 // indirect 87 | github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect 88 | github.com/pkg/errors v0.9.1 // indirect 89 | github.com/pkg/profile v1.7.0 90 | github.com/pmezard/go-difflib v1.0.0 // indirect 91 | github.com/pseudomuto/protoc-gen-doc v1.5.1 // indirect 92 | github.com/pseudomuto/protokit v0.2.0 // indirect 93 | github.com/rogpeppe/go-internal v1.10.0 // indirect 94 | github.com/russross/blackfriday/v2 v2.1.0 // indirect 95 | github.com/spf13/cobra v1.7.0 // indirect 96 | github.com/spf13/pflag v1.0.5 // indirect 97 | github.com/stretchr/testify v1.9.0 98 | go.uber.org/atomic v1.11.0 // indirect 99 | go.uber.org/multierr v1.11.0 // indirect 100 | go.uber.org/zap v1.24.0 // indirect 101 | golang.org/x/crypto v0.21.0 // indirect 102 | golang.org/x/exp v0.0.0-20231006140011-7918f672742d 103 | golang.org/x/mod v0.16.0 104 | golang.org/x/net v0.22.0 // indirect 105 | golang.org/x/sys v0.18.0 // indirect 106 | golang.org/x/term v0.18.0 // indirect 107 | golang.org/x/text v0.14.0 // indirect 108 | google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4 // indirect 109 | google.golang.org/protobuf v1.31.0 110 | gopkg.in/yaml.v3 v3.0.1 // indirect 111 | ) 112 | -------------------------------------------------------------------------------- /internal/command/command.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "os/exec" 5 | "strings" 6 | ) 7 | 8 | // Run runs the given command using the given working directory. If the command succeeds, 9 | // the value of stdout is returned with trailing whitespace removed. If the command fails, 10 | // the combined stdout/stderr text will also be returned. 11 | func Run(dir, command string, args ...string) (string, error) { 12 | cmd := exec.Command(command, args...) 13 | cmd.Dir = dir 14 | 15 | out, err := cmd.CombinedOutput() 16 | return strings.TrimSpace(string(out)), err 17 | } 18 | -------------------------------------------------------------------------------- /internal/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | ) 7 | 8 | type IndexOpts struct { 9 | ModuleRoot string 10 | ModuleVersion string 11 | 12 | // Path for the current module we are indexing. Same as packages.Package.Module.Path 13 | ModulePath string 14 | 15 | IsGoPackagesDriverSet bool 16 | 17 | // Go version. Used for linking to the Go standard library 18 | GoStdlibVersion string 19 | 20 | // Whether we should emit implementations 21 | SkipImplementations bool 22 | SkipTests bool 23 | 24 | IsIndexingStdlib bool 25 | 26 | // Package patterns to index 27 | PackagePatterns []string 28 | } 29 | 30 | func New(ModuleRoot, ModuleVersion, ModulePath, GoStdlibVersion string, IsIndexingStdlib bool, SkipImplementations bool, SkipTests bool, PackagePatterns []string) IndexOpts { 31 | ModuleRoot, err := filepath.Abs(ModuleRoot) 32 | if err != nil { 33 | panic(err) 34 | } 35 | 36 | driver := os.Getenv("GOPACKAGESDRIVER") 37 | isGoPackagesDriverSet := driver != "" && driver != "off" 38 | 39 | return IndexOpts{ 40 | ModuleRoot: ModuleRoot, 41 | ModuleVersion: ModuleVersion, 42 | ModulePath: ModulePath, 43 | GoStdlibVersion: GoStdlibVersion, 44 | SkipImplementations: SkipImplementations, 45 | SkipTests: SkipTests, 46 | IsIndexingStdlib: IsIndexingStdlib, 47 | PackagePatterns: PackagePatterns, 48 | IsGoPackagesDriverSet: isGoPackagesDriverSet, 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /internal/funk/funk.go: -------------------------------------------------------------------------------- 1 | package funk 2 | 3 | import ( 4 | "slices" 5 | 6 | "golang.org/x/exp/constraints" 7 | "golang.org/x/exp/maps" 8 | ) 9 | 10 | func SortedKeys[K constraints.Ordered, V any](m map[K]V) []K { 11 | keys := maps.Keys(m) 12 | slices.Sort(keys) 13 | return keys 14 | } 15 | 16 | func Map[T any, V any](l []T, f func(T) V) []V { 17 | vals := make([]V, 0, len(l)) 18 | for i, v := range l { 19 | vals[i] = f(v) 20 | } 21 | 22 | return vals 23 | } 24 | -------------------------------------------------------------------------------- /internal/git/infer_module_version.go: -------------------------------------------------------------------------------- 1 | package git 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/weightylarva/scip-go/internal/command" 7 | ) 8 | 9 | // InferModuleVersion returns the version of the module declared in the given 10 | // directory. This will be either the work tree commit's tag, or it will be the 11 | // short revhash of the HEAD commit. 12 | func InferModuleVersion(dir string) (string, error) { 13 | version, err := command.Run(dir, "git", "tag", "-l", "--points-at", "HEAD") 14 | if err != nil { 15 | return "", fmt.Errorf("failed to tags for current commit: %v\n%s", err, version) 16 | } 17 | if version != "" { 18 | return version, nil 19 | } 20 | 21 | commit, err := command.Run(dir, "git", "rev-parse", "HEAD") 22 | if err != nil { 23 | return "", fmt.Errorf("failed to get current commit: %v\n%s", err, commit) 24 | } 25 | 26 | return commit[:12], nil 27 | } 28 | -------------------------------------------------------------------------------- /internal/git/infer_repo.go: -------------------------------------------------------------------------------- 1 | package git 2 | 3 | import ( 4 | "fmt" 5 | "net/url" 6 | "strings" 7 | 8 | "github.com/weightylarva/scip-go/internal/command" 9 | ) 10 | 11 | // InferRepo gets a human-readable repository name from the git clone enclosing 12 | // the given directory. 13 | func InferRepo(dir string) (string, error) { 14 | remoteURL, err := command.Run(dir, "git", "remote", "get-url", "origin") 15 | if err != nil { 16 | return "", err 17 | } 18 | 19 | return parseRemote(remoteURL) 20 | } 21 | 22 | // parseRemote converts a git origin url into a Sourcegraph-friendly repo name. 23 | func parseRemote(remoteURL string) (string, error) { 24 | // e.g., git@github.com:sourcegraph/scip-go.git 25 | if strings.HasPrefix(remoteURL, "git@") { 26 | if parts := strings.Split(remoteURL, ":"); len(parts) == 2 { 27 | return strings.Join([]string{ 28 | strings.TrimPrefix(parts[0], "git@"), 29 | strings.TrimSuffix(parts[1], ".git"), 30 | }, "/"), nil 31 | } 32 | } 33 | 34 | // e.g., https://github.com/weightylarva/scip-go.git 35 | if url, err := url.Parse(remoteURL); err == nil { 36 | return url.Hostname() + strings.TrimSuffix(url.Path, ".git"), nil 37 | } 38 | 39 | return "", fmt.Errorf("unrecognized remote URL: %s", remoteURL) 40 | } 41 | -------------------------------------------------------------------------------- /internal/git/infer_repo_test.go: -------------------------------------------------------------------------------- 1 | package git 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestInferRepo(t *testing.T) { 9 | repo, err := InferRepo("") 10 | if err != nil { 11 | t.Fatalf("unexpected error inferring repo: %s", err) 12 | } 13 | 14 | if repo != "github.com/weightylarva/scip-go" { 15 | t.Errorf("unexpected remote repo. want=%q have=%q", "github.com/weightylarva/scip-go", repo) 16 | } 17 | } 18 | 19 | func TestParseRemote(t *testing.T) { 20 | testCases := map[string]string{ 21 | "git@github.com:sourcegraph/scip-go.git": "github.com/weightylarva/scip-go", 22 | "https://github.com/weightylarva/scip-go": "github.com/weightylarva/scip-go", 23 | "ssh://git@phabricator.company.com:2222/diffusion/COMPANY/companay.git": "phabricator.company.com/diffusion/COMPANY/companay", 24 | } 25 | 26 | for input, expectedOutput := range testCases { 27 | t.Run(fmt.Sprintf("input=%q", input), func(t *testing.T) { 28 | output, err := parseRemote(input) 29 | if err != nil { 30 | t.Fatalf("unexpected error parsing remote: %s", err) 31 | } 32 | 33 | if output != expectedOutput { 34 | t.Errorf("unexpected repo name. want=%q have=%q", expectedOutput, output) 35 | } 36 | }) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /internal/git/toplevel.go: -------------------------------------------------------------------------------- 1 | package git 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/weightylarva/scip-go/internal/command" 8 | ) 9 | 10 | // TopLevel returns the root of the git project containing the given directory. 11 | func TopLevel(dir string) (string, error) { 12 | output, err := command.Run(dir, "git", "rev-parse", "--show-toplevel") 13 | if err != nil { 14 | return "", fmt.Errorf("failed to get toplevel: %v\n%s", err, output) 15 | } 16 | 17 | return strings.TrimSpace(string(output)), nil 18 | } 19 | -------------------------------------------------------------------------------- /internal/handler/handler.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import "fmt" 4 | 5 | var devMode bool = false 6 | 7 | func SetDev(dev bool) { 8 | devMode = dev 9 | } 10 | 11 | func ErrOrPanic(format string, a ...any) error { 12 | if devMode { 13 | panic(fmt.Sprintf(format, a...)) 14 | } 15 | 16 | return fmt.Errorf(format, a...) 17 | } 18 | -------------------------------------------------------------------------------- /internal/index/package_ident.go: -------------------------------------------------------------------------------- 1 | package index 2 | 3 | import ( 4 | "go/ast" 5 | "math" 6 | "path" 7 | "strings" 8 | 9 | "github.com/agnivade/levenshtein" 10 | "golang.org/x/tools/go/packages" 11 | ) 12 | 13 | func findBestPackageDefinitionPath(pkg *packages.Package) (*ast.File, error) { 14 | if pkg.PkgPath == "builtin" { 15 | return nil, nil 16 | } 17 | 18 | // Unsafe is special case for builtin 19 | if pkg.PkgPath == "unsafe" { 20 | return nil, nil 21 | } 22 | 23 | if len(pkg.Syntax) == 0 { 24 | // This case can be triggered when a package directory only contains `_test.go` files, 25 | // as those files will be compiled as part of a separate _test package. 26 | return nil, nil 27 | } 28 | 29 | files := []*ast.File{} 30 | filesWithDocs := []*ast.File{} 31 | for _, f := range pkg.Syntax { 32 | // pos := pkg.Fset.Position(f.Pos()) 33 | 34 | files = append(files, f) 35 | if f.Doc != nil { 36 | filesWithDocs = append(filesWithDocs, f) 37 | } 38 | } 39 | 40 | // The idiomatic way is to _only_ have one .go file per package that has a docstring 41 | // for the package. This should generally return here. 42 | if len(filesWithDocs) == 1 { 43 | return filesWithDocs[0], nil 44 | } 45 | 46 | // If we for some reason have more than one .go file per package that has a docstring, 47 | // only consider returning paths that contain the docstring (instead of any of the possible 48 | // paths). 49 | if len(filesWithDocs) > 1 { 50 | files = filesWithDocs 51 | } 52 | 53 | // Try to only pick non _test files for non _test packages and vice versa. 54 | files = filterBasedOnTestFiles(pkg, files) 55 | 56 | // Find the best remaining path. 57 | // Chooses: 58 | // 1. doc.go 59 | // 2. exact match 60 | // 3. computes levenshtein and picks best score 61 | var bestFile *ast.File 62 | 63 | minDistance := math.MaxInt32 64 | for _, f := range files { 65 | fPath := pkg.Fset.Position(f.Pos()).Filename 66 | fileName := fileNameWithoutExtension(fPath) 67 | 68 | if "doc.go" == path.Base(fPath) { 69 | return f, nil 70 | } 71 | 72 | if pkg.Name == fileName { 73 | return f, nil 74 | } 75 | 76 | distance := levenshtein.ComputeDistance(pkg.Name, fileName) 77 | if distance < minDistance { 78 | minDistance = distance 79 | bestFile = f 80 | } 81 | } 82 | 83 | return bestFile, nil 84 | } 85 | 86 | func fileNameWithoutExtension(fileName string) string { 87 | return strings.TrimSuffix(fileName, path.Ext(fileName)) 88 | } 89 | 90 | func filterBasedOnTestFiles(pkg *packages.Package, files []*ast.File) []*ast.File { 91 | packageNameEndsWithTest := strings.HasSuffix(pkg.Name, "_test") 92 | 93 | preferredFiles := []*ast.File{} 94 | for _, f := range files { 95 | fPath := pkg.Fset.Position(f.Pos()) 96 | if packageNameEndsWithTest == strings.HasSuffix(fPath.Filename, "_test.go") { 97 | preferredFiles = append(preferredFiles, f) 98 | } 99 | } 100 | 101 | if len(preferredFiles) > 0 { 102 | return preferredFiles 103 | } 104 | 105 | return files 106 | } 107 | -------------------------------------------------------------------------------- /internal/index/package_ident_test.go: -------------------------------------------------------------------------------- 1 | package index 2 | 3 | import ( 4 | "go/ast" 5 | "go/token" 6 | "testing" 7 | 8 | "golang.org/x/tools/go/packages" 9 | ) 10 | 11 | func TestIndexer_findBestPackageDefinitionPath(t *testing.T) { 12 | type FileInfo struct { 13 | Name string 14 | Docs bool 15 | } 16 | 17 | makePackage := func(pkgName string, fileInfo []FileInfo) (*packages.Package, map[*ast.File]string) { 18 | fset := token.NewFileSet() 19 | 20 | files := map[string]*ast.File{} 21 | syntax := []*ast.File{} 22 | posMap := map[*ast.File]string{} 23 | 24 | for idx, info := range fileInfo { 25 | var doc *ast.CommentGroup 26 | if info.Docs { 27 | doc = &ast.CommentGroup{} 28 | } 29 | 30 | f := &ast.File{ 31 | Doc: doc, 32 | Package: 0, 33 | Name: &ast.Ident{ 34 | NamePos: token.Pos(idx), 35 | Name: pkgName, 36 | Obj: &ast.Object{}, 37 | }, 38 | } 39 | 40 | files[info.Name] = f 41 | syntax = append(syntax, f) 42 | posMap[f] = info.Name 43 | 44 | fset.AddFile(info.Name, fset.Base(), 1) 45 | } 46 | 47 | return &packages.Package{ 48 | ID: "test-package", 49 | Name: pkgName, 50 | PkgPath: "test-package", 51 | Imports: map[string]*packages.Package{}, 52 | Fset: fset, 53 | Syntax: syntax, 54 | }, posMap 55 | } 56 | 57 | makeTest := func(name, pkgName, expected string, fileInfo []FileInfo) { 58 | t.Run(name, func(t *testing.T) { 59 | pkg, names := makePackage(pkgName, fileInfo) 60 | 61 | pkgToken, _ := findBestPackageDefinitionPath(pkg) 62 | if name := names[pkgToken]; name != expected { 63 | t.Errorf("incorrect hover text documentation. want=%s have=%s", name, expected) 64 | } 65 | }) 66 | } 67 | 68 | makeTest("Should find exact name match", 69 | "smol", 70 | "smol.go", 71 | []FileInfo{ 72 | {"smol.go", false}, 73 | {"other.go", false}, 74 | }, 75 | ) 76 | 77 | makeTest("Should return something even if nothing matches", 78 | "smol", 79 | "random.go", 80 | []FileInfo{ 81 | {"random.go", false}, 82 | }, 83 | ) 84 | 85 | makeTest("Should not pick _test files if package is not a test package", 86 | "unreleated", 87 | "smol.go", 88 | []FileInfo{ 89 | {"smol.go", false}, 90 | {"smol_test.go", false}, 91 | }, 92 | ) 93 | 94 | makeTest("Pick whatever has documentation", 95 | "mylib", 96 | "has_docs.go", 97 | []FileInfo{ 98 | {"mylib.go", false}, 99 | {"has_docs.go", true}, 100 | }, 101 | ) 102 | 103 | makeTest("should pick a name that is a closer edit distance than one far away", 104 | "http_router", 105 | "httprouter.go", 106 | []FileInfo{ 107 | {"httprouter.go", false}, 108 | {"httpother.go", false}, 109 | }, 110 | ) 111 | 112 | makeTest("should prefer test packages over other packages if the package name has test suffix", 113 | "mylib_test", 114 | "mylib_test.go", 115 | []FileInfo{ 116 | {"mylib_test.go", false}, 117 | {"mylib.go", false}, 118 | }, 119 | ) 120 | } 121 | -------------------------------------------------------------------------------- /internal/index/scip_test.go: -------------------------------------------------------------------------------- 1 | package index_test 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "net/url" 7 | "os" 8 | "path/filepath" 9 | "strings" 10 | "testing" 11 | 12 | "github.com/weightylarva/scip-go/internal/command" 13 | "github.com/weightylarva/scip-go/internal/config" 14 | "github.com/weightylarva/scip-go/internal/index" 15 | "github.com/sourcegraph/scip/bindings/go/scip" 16 | "github.com/sourcegraph/scip/bindings/go/scip/testutil" 17 | "google.golang.org/protobuf/proto" 18 | ) 19 | 20 | // Use "update-snapshots" to update snapshots 21 | var filter = flag.String("filter", "", "filenames to filter by") 22 | 23 | func TestSnapshots(t *testing.T) { 24 | snapshotRoot := getTestdataRoot(t) 25 | 26 | testutil.SnapshotTest(t, 27 | snapshotRoot, 28 | func(inputDirectory, outputDirectory string, sources []*scip.SourceFile) []*scip.SourceFile { 29 | fmt.Println("Indexing", inputDirectory, "outputDirectory", outputDirectory) 30 | 31 | if *filter != "" && !strings.Contains(inputDirectory, *filter) { 32 | return []*scip.SourceFile{} 33 | } 34 | 35 | scipIndex := scip.Index{} 36 | writer := func(msg proto.Message) { 37 | switch msg := msg.(type) { 38 | case *scip.Metadata: 39 | scipIndex.Metadata = msg 40 | case *scip.Document: 41 | scipIndex.Documents = append(scipIndex.Documents, msg) 42 | case *scip.SymbolInformation: 43 | scipIndex.ExternalSymbols = append(scipIndex.ExternalSymbols, msg) 44 | } 45 | } 46 | 47 | err := index.Index(writer, config.IndexOpts{ 48 | ModuleRoot: inputDirectory, 49 | ModuleVersion: "0.1.test", 50 | ModulePath: "sg/" + filepath.Base(inputDirectory), 51 | GoStdlibVersion: "go1.22", 52 | }) 53 | if err != nil { 54 | t.Fatal(err) 55 | } 56 | 57 | symbolFormatter := scip.SymbolFormatter{ 58 | OnError: func(err error) error { return err }, 59 | IncludeScheme: func(scheme string) bool { return scheme == "local" }, 60 | IncludePackageManager: func(_ string) bool { return false }, 61 | IncludePackageName: func(name string) bool { return !strings.HasPrefix(name, "sg/") }, 62 | IncludePackageVersion: func(_ string) bool { return true }, 63 | IncludeDescriptor: func(_ string) bool { return true }, 64 | IncludeRawDescriptor: func(descriptor *scip.Descriptor) bool { return true }, 65 | IncludeDisambiguator: func(_ string) bool { return true }, 66 | } 67 | 68 | sourceFiles := []*scip.SourceFile{} 69 | for _, doc := range scipIndex.Documents { 70 | // Skip files outside of current directory 71 | if strings.HasPrefix(doc.RelativePath, "..") { 72 | continue 73 | } 74 | 75 | if *filter != "" && !strings.Contains(doc.RelativePath, *filter) { 76 | continue 77 | } 78 | 79 | sourcePath, _ := url.JoinPath(scipIndex.Metadata.ProjectRoot, doc.RelativePath) 80 | sourceUrl, _ := url.Parse(sourcePath) 81 | formatted, err := testutil.FormatSnapshot(doc, "//", symbolFormatter, sourceUrl.Path) 82 | if err != nil { 83 | t.Errorf("Failed to format document: %s // %s", sourceUrl.Path, err) 84 | } 85 | 86 | sourceFiles = append(sourceFiles, scip.NewSourceFile( 87 | doc.RelativePath, 88 | doc.RelativePath, 89 | formatted, 90 | )) 91 | } 92 | 93 | return sourceFiles 94 | }, 95 | ) 96 | } 97 | 98 | // getTestdataRoot returns the absolute path to the testdata directory of this repository. 99 | func getTestdataRoot(t *testing.T) string { 100 | wd, err := os.Getwd() 101 | if err != nil { 102 | t.Fatalf("unexpected error getting working directory: %s", err) 103 | } 104 | 105 | root, err := command.Run(wd, "git", "rev-parse", "--show-toplevel") 106 | if err != nil { 107 | t.Fatalf("unexpected error getting working directory: %s", err) 108 | } 109 | 110 | testdata, err := filepath.Abs(filepath.Join(root, "internal/testdata")) 111 | if err != nil { 112 | t.Fatalf("unexpected error getting absolute directory: %s", err) 113 | } 114 | 115 | return testdata 116 | } 117 | -------------------------------------------------------------------------------- /internal/index/version.txt: -------------------------------------------------------------------------------- 1 | 0.1.24 2 | -------------------------------------------------------------------------------- /internal/loader/loader_test.go: -------------------------------------------------------------------------------- 1 | package loader 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "strings" 7 | "testing" 8 | 9 | "github.com/weightylarva/scip-go/internal/config" 10 | "github.com/stretchr/testify/require" 11 | "golang.org/x/mod/module" 12 | "golang.org/x/tools/go/packages" 13 | ) 14 | 15 | func TestBuiltinFormat(t *testing.T) { 16 | wd, _ := os.Getwd() 17 | root, _ := filepath.Abs(filepath.Join(wd, "../../")) 18 | pkgConfig := getConfig(root, config.IndexOpts{}) 19 | pkgConfig.Tests = false 20 | 21 | pkgs, err := packages.Load(pkgConfig, "fmt") 22 | if err != nil { 23 | t.Fatal(err) 24 | } 25 | 26 | if len(pkgs) != 1 { 27 | t.Fatalf("Too many packages: %s", pkgs) 28 | } 29 | 30 | fmtPkg := pkgs[0] 31 | 32 | if !IsStandardLib(fmtPkg) { 33 | t.Fatal("Package was not a builtin package: pre ensure") 34 | } 35 | 36 | // TODO: don't use nil? 37 | normalizePackage(&config.IndexOpts{}, fmtPkg) 38 | 39 | if !IsStandardLib(fmtPkg) { 40 | t.Fatal("Package was not a builtin package: post ensure") 41 | } 42 | } 43 | 44 | type normalizeTestCase struct { 45 | Raw string 46 | Normalized string 47 | } 48 | 49 | func TestNormalizePackageModuleVersion(t *testing.T) { 50 | cases := []normalizeTestCase{ 51 | { 52 | Raw: "v0.0.0-20180920160851-f15b22f93c73", 53 | Normalized: "f15b22f93c73", 54 | }, 55 | { 56 | Raw: "v0.3.1-0.20230414160720-beea233bdc0b", 57 | Normalized: "beea233bdc0b", 58 | }, 59 | { 60 | Raw: "v2.0.0-20180818164646-67afb5ed74ec", 61 | Normalized: "67afb5ed74ec", 62 | }, 63 | { 64 | Raw: "v1.1.1", 65 | Normalized: "v1.1.1", 66 | }, 67 | { 68 | Raw: "v1.0.0-beta.1", 69 | Normalized: "v1.0.0-beta.1", 70 | }, 71 | { 72 | Raw: "v0.0.0", 73 | Normalized: "v0.0.0", 74 | }, 75 | { 76 | Raw: "v2.0.0+incompatible", 77 | Normalized: "v2.0.0", 78 | }, 79 | { 80 | Raw: "", 81 | Normalized: ".", 82 | }, 83 | } 84 | 85 | for _, testCase := range cases { 86 | pkg := &packages.Package{ 87 | PkgPath: "github.com/fake_name/fake_module/fake_package", 88 | Module: &packages.Module{ 89 | Path: "github.com/fake_name/fake_module", 90 | Version: testCase.Raw, 91 | }, 92 | } 93 | normalizePackage(&config.IndexOpts{}, pkg) 94 | 95 | require.Equal(t, testCase.Normalized, pkg.Module.Version) 96 | } 97 | } 98 | 99 | func TestPackagePseudoVersion(t *testing.T) { 100 | wd, _ := os.Getwd() 101 | root, _ := filepath.Abs(filepath.Join(wd, "../../")) 102 | pkgConfig := getConfig(root, config.IndexOpts{}) 103 | pkgConfig.Tests = false 104 | 105 | pkgs, err := packages.Load(pkgConfig, "github.com/efritz/pentimento") 106 | require.Nil(t, err) 107 | 108 | require.Equal(t, 1, len(pkgs), "Too many packages") 109 | 110 | pkg := pkgs[0] 111 | 112 | require.True(t, module.IsPseudoVersion(pkg.Module.Version), "Package did not have a pseudo version: pre ensure") 113 | 114 | normalizePackage(&config.IndexOpts{}, pkg) 115 | 116 | require.Equal(t, "ade47d831101", pkg.Module.Version, "Package pseudo-version was not extracted into a sha: post ensure") 117 | } 118 | 119 | func TestPackageWithinModule(t *testing.T) { 120 | wd, _ := os.Getwd() 121 | root, _ := filepath.Abs(filepath.Join(wd, "../../")) 122 | 123 | config := getConfig(root, config.IndexOpts{}) 124 | config.Tests = false 125 | 126 | _, err := packages.Load(config, "./...") 127 | if err != nil { 128 | t.Fatal(err) 129 | } 130 | } 131 | 132 | func TestPentimentoPackage(t *testing.T) { 133 | // "github.com/efritz/pentimento" 134 | wd, _ := os.Getwd() 135 | root, _ := filepath.Abs(filepath.Join(wd, "../../")) 136 | 137 | config := getConfig(root, config.IndexOpts{}) 138 | config.Tests = false 139 | 140 | // TODO: Could possibly just load this way as well :) 141 | // packages.Load(config, "github.com/efritz/pentimento") 142 | pkgs, err := packages.Load(config, "./...") 143 | if err != nil { 144 | t.Fatal(err) 145 | } 146 | 147 | var pentimento *packages.Package 148 | for _, pkg := range pkgs { 149 | for _, imported := range pkg.Imports { 150 | if strings.Contains(imported.Name, "pentimento") { 151 | pentimento = imported 152 | break 153 | } 154 | } 155 | } 156 | 157 | if pentimento == nil { 158 | t.Fatal("Could not find pentimento dep") 159 | } 160 | 161 | if "pentimento" != pentimento.Name || 162 | "github.com/efritz/pentimento" != pentimento.PkgPath || 163 | "github.com/efritz/pentimento" != pentimento.Module.Path { 164 | 165 | t.Fatal("Did not match module") 166 | } 167 | // Name string = "pentimento" 168 | // PkgPath string = "github.com/efritz/pentimento" 169 | // Module: 170 | // Path string = "github.com/efritz/pentimento" 171 | // Version string = "v0.0.0-20190429011147-ade47d831101" 172 | } 173 | -------------------------------------------------------------------------------- /internal/loader/stdlib.go: -------------------------------------------------------------------------------- 1 | // THIS FILE IS GENERATED. SEE ./scripts/gen_std_lib.sh 2 | // Generated by: go version go1.24.0 darwin/arm64 3 | package loader 4 | 5 | var contained = struct{}{} 6 | 7 | // This list is calculated from "go list std". 8 | var stdPackages = map[string]struct{}{ 9 | "archive": contained, 10 | "bufio": contained, 11 | "bytes": contained, 12 | "cmp": contained, 13 | "compress": contained, 14 | "container": contained, 15 | "context": contained, 16 | "crypto": contained, 17 | "database": contained, 18 | "debug": contained, 19 | "embed": contained, 20 | "encoding": contained, 21 | "errors": contained, 22 | "expvar": contained, 23 | "flag": contained, 24 | "fmt": contained, 25 | "go": contained, 26 | "hash": contained, 27 | "html": contained, 28 | "image": contained, 29 | "index": contained, 30 | "internal": contained, 31 | "io": contained, 32 | "iter": contained, 33 | "log": contained, 34 | "maps": contained, 35 | "math": contained, 36 | "mime": contained, 37 | "net": contained, 38 | "os": contained, 39 | "path": contained, 40 | "plugin": contained, 41 | "reflect": contained, 42 | "regexp": contained, 43 | "runtime": contained, 44 | "slices": contained, 45 | "sort": contained, 46 | "strconv": contained, 47 | "strings": contained, 48 | "structs": contained, 49 | "sync": contained, 50 | "syscall": contained, 51 | "testing": contained, 52 | "text": contained, 53 | "time": contained, 54 | "unicode": contained, 55 | "unique": contained, 56 | "unsafe": contained, 57 | "vendor": contained, 58 | "weak": contained, 59 | } 60 | -------------------------------------------------------------------------------- /internal/lookup/lookup.go: -------------------------------------------------------------------------------- 1 | package lookup 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "go/ast" 7 | "go/token" 8 | "go/types" 9 | "sync" 10 | 11 | "github.com/weightylarva/scip-go/internal/newtypes" 12 | "github.com/weightylarva/scip-go/internal/output" 13 | "github.com/weightylarva/scip-go/internal/symbols" 14 | "github.com/sourcegraph/scip/bindings/go/scip" 15 | "golang.org/x/tools/go/packages" 16 | ) 17 | 18 | func NewPackageSymbols(pkg *packages.Package) *Package { 19 | return &Package{ 20 | pkg: pkg, 21 | fields: map[token.Pos]*scip.SymbolInformation{}, 22 | } 23 | } 24 | 25 | func NewGlobalSymbols() *Global { 26 | return &Global{ 27 | symbols: map[newtypes.PackageID]*Package{}, 28 | pkgNames: map[newtypes.PackageID]*PackageName{}, 29 | } 30 | } 31 | 32 | type Package struct { 33 | pkg *packages.Package 34 | fields map[token.Pos]*scip.SymbolInformation 35 | } 36 | 37 | func (p *Package) SymbolsForFile(file *token.File) []*scip.SymbolInformation { 38 | var documentSymbols []*scip.SymbolInformation = nil 39 | for pos, symbol := range p.fields { 40 | if p.pkg.Fset.File(pos) == file { 41 | documentSymbols = append(documentSymbols, symbol) 42 | } 43 | } 44 | 45 | return documentSymbols 46 | } 47 | 48 | var emittedLogLine = map[token.Pos]struct{}{} 49 | var emittedLogLineMu sync.Mutex 50 | 51 | func (p *Package) Set(pos token.Pos, symbol *scip.SymbolInformation) { 52 | if original, ok := p.fields[pos]; ok { 53 | if original != symbol { 54 | // Workaround for handling symbol names when multiple 55 | // fields are defined in the same statement with the same anonymous 56 | // struct type. By ignoring this case, the last field name will 57 | // be used for the type name. 58 | // Ideal fix: https://github.com/weightylarva/scip-go/issues/95 59 | emittedLogLineMu.Lock() 60 | if _, ok := emittedLogLine[pos]; !ok { 61 | output.Logf("[scip.lookup] Overriding original symbol %s with %s at %v", original.Symbol, symbol.Symbol, p.pkg.Fset.Position(pos)) 62 | emittedLogLine[pos] = struct{}{} 63 | } 64 | emittedLogLineMu.Unlock() 65 | } 66 | } 67 | 68 | p.fields[pos] = symbol 69 | } 70 | 71 | func (p *Package) Get(pos token.Pos) (*scip.SymbolInformation, bool) { 72 | field, ok := p.fields[pos] 73 | return field, ok 74 | } 75 | 76 | func (p *Package) GetSymbol(pos token.Pos) (string, bool) { 77 | field, ok := p.Get(pos) 78 | if ok && field != nil { 79 | return field.Symbol, true 80 | } else { 81 | return "", false 82 | } 83 | } 84 | 85 | type PackageName struct { 86 | Symbol *scip.SymbolInformation 87 | Pos token.Pos 88 | } 89 | 90 | type Global struct { 91 | m sync.Mutex 92 | symbols map[newtypes.PackageID]*Package 93 | pkgNames map[newtypes.PackageID]*PackageName 94 | } 95 | 96 | func (p *Global) Add(pkgSymbols *Package) { 97 | p.m.Lock() 98 | p.symbols[newtypes.GetID(pkgSymbols.pkg)] = pkgSymbols 99 | p.m.Unlock() 100 | } 101 | 102 | func (p *Global) SetPkgName(pkg *packages.Package, pkgDeclaration *ast.File) { 103 | p.m.Lock() 104 | p.pkgNames[newtypes.GetID(pkg)] = &PackageName{ 105 | Symbol: &scip.SymbolInformation{ 106 | Symbol: symbols.FromDescriptors(pkg, &scip.Descriptor{ 107 | Name: pkg.PkgPath, 108 | Suffix: scip.Descriptor_Namespace, 109 | }), 110 | Documentation: []string{}, 111 | Relationships: []*scip.Relationship{}, 112 | }, 113 | Pos: pkgDeclaration.Name.NamePos, 114 | } 115 | p.m.Unlock() 116 | } 117 | 118 | func (p *Global) GetPkgNameSymbolByID(pkgID newtypes.PackageID) *scip.SymbolInformation { 119 | named, ok := p.pkgNames[pkgID] 120 | if !ok { 121 | return nil 122 | } 123 | 124 | return named.Symbol 125 | } 126 | 127 | func (p *Global) GetPkgNameSymbol(pkg *packages.Package) *scip.SymbolInformation { 128 | return p.GetPkgNameSymbolByID(newtypes.GetID(pkg)) 129 | } 130 | 131 | func (p *Global) GetPackage(pkg *packages.Package) *Package { 132 | return p.symbols[newtypes.GetID(pkg)] 133 | } 134 | 135 | var skippedTypes = map[string]struct{}{} 136 | var builtinSymbols = map[string]*scip.SymbolInformation{} 137 | 138 | // GetSymbolOfObject returns a symbol and whether we were successful at finding. 139 | // 140 | // We can return an empty string if this object should be ignored. 141 | func (p *Global) GetSymbolOfObject(obj types.Object) (*scip.SymbolInformation, bool, error) { 142 | if _, ok := skippedTypes[obj.Id()]; ok { 143 | return nil, false, nil 144 | } 145 | 146 | if sym, ok := builtinSymbols[obj.Id()]; ok { 147 | return sym, true, nil 148 | } 149 | 150 | switch obj := obj.(type) { 151 | case *types.PkgName: 152 | panic(fmt.Sprintf("should never lookup PkgName %s | %+v", obj.Id(), obj.Imported().Path())) 153 | case *types.Nil: 154 | return nil, false, nil 155 | } 156 | 157 | pkg := obj.Pkg() 158 | if pkg == nil { 159 | switch obj := obj.(type) { 160 | case *types.TypeName: 161 | skippedTypes[obj.Id()] = struct{}{} 162 | return nil, false, nil 163 | case *types.Const: 164 | return nil, false, nil 165 | case *types.Builtin: 166 | return nil, false, nil 167 | case *types.Func: 168 | if orig := obj.Origin(); orig != nil { 169 | name := orig.FullName() 170 | switch name { 171 | case "(error).Error": 172 | return nil, false, nil 173 | } 174 | } 175 | } 176 | 177 | panic(fmt.Sprintf("failed to create symbol for builtin obj: %T %+v | %s", obj, obj, obj.Id())) 178 | } 179 | 180 | pkgPath := pkg.Path() 181 | for _, combination := range testPackageCombinations(pkgPath) { 182 | symbol, _, ok := p.getSymbolInformationByPath(combination, obj.Pos()) 183 | if ok { 184 | return symbol, true, nil 185 | } 186 | } 187 | 188 | switch obj := obj.(type) { 189 | case *types.Var: 190 | // , "| position", pkg.Fset.Position(obj.Pos()))) 191 | return nil, false, errors.New(fmt.Sprintln("obj", obj, "| origin", obj.Origin())) 192 | } 193 | 194 | return nil, false, errors.New(fmt.Sprintf( 195 | "failed to create symbol for obj: %T %+v\n%s", 196 | obj, 197 | obj, 198 | pkgPath, 199 | )) 200 | } 201 | 202 | func (p *Global) getSymbolInformationByPath(pkgID newtypes.PackageID, pos token.Pos) (*scip.SymbolInformation, *Package, bool) { 203 | pkgFields, ok := p.symbols[pkgID] 204 | if !ok { 205 | return nil, nil, false 206 | } 207 | 208 | field, ok := pkgFields.Get(pos) 209 | return field, pkgFields, ok 210 | } 211 | 212 | func (p *Global) GetSymbolInformation(pkg *packages.Package, pos token.Pos) (*scip.SymbolInformation, bool) { 213 | info, _, ok := p.getSymbolInformationByPath(newtypes.GetID(pkg), pos) 214 | return info, ok 215 | } 216 | 217 | func (p *Global) GetSymbol(pkg *packages.Package, pos token.Pos) (string, bool) { 218 | field, ok := p.GetSymbolInformation(pkg, pos) 219 | if ok && field != nil { 220 | return field.Symbol, true 221 | } else { 222 | return "", false 223 | } 224 | } 225 | 226 | func testPackageCombinations(pkgPath string) []newtypes.PackageID { 227 | return []newtypes.PackageID{ 228 | newtypes.PackageID(pkgPath), 229 | newtypes.PackageID(fmt.Sprintf("%s.test", pkgPath)), 230 | newtypes.PackageID(fmt.Sprintf("%s [%s.test]", pkgPath, pkgPath)), 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /internal/modules/modules.go: -------------------------------------------------------------------------------- 1 | package modules 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path/filepath" 7 | "strings" 8 | 9 | "github.com/charmbracelet/log" 10 | "github.com/weightylarva/scip-go/internal/command" 11 | "github.com/weightylarva/scip-go/internal/output" 12 | "golang.org/x/tools/go/vcs" 13 | ) 14 | 15 | func ModuleName(dir, repo, inName string) (moduleName string, isStdLib bool, err error) { 16 | resolve := func() error { 17 | if inName != "" { 18 | moduleName = inName 19 | return nil 20 | } 21 | 22 | moduleName = repo 23 | 24 | if !isModule(dir) { 25 | log.Warn("No go.mod file found in current directory.") 26 | } else { 27 | if moduleName, err = command.Run(dir, "go", "list", "-mod=readonly", "-m"); err != nil { 28 | return fmt.Errorf("failed to list modules: %v\n%s", err, moduleName) 29 | } 30 | 31 | return nil 32 | } 33 | 34 | moduleName, isStdLib, err = resolveModuleName(repo, moduleName) 35 | 36 | return nil 37 | } 38 | 39 | err = output.WithProgress("Resolving module name", resolve) 40 | if err != nil { 41 | return "", false, err 42 | } 43 | 44 | if moduleName == "std" { 45 | isStdLib = true 46 | } 47 | 48 | return moduleName, isStdLib, err 49 | } 50 | 51 | // resolveModuleName converts the given repository and import path into a canonical 52 | // representation of a module name usable for moniker identifiers. The base of the 53 | // import path will be the resolved repository remote, and the given module name 54 | // is used only to determine the path suffix. 55 | func resolveModuleName(repo, name string) (string, bool, error) { 56 | // Determine path suffix relative to repository root 57 | var suffix string 58 | 59 | if nameRepoRoot, err := vcs.RepoRootForImportPath(name, false); err == nil { 60 | suffix = strings.TrimPrefix(name, nameRepoRoot.Root) 61 | } else { 62 | // A user-visible warning will occur on this path as the declared 63 | // module will be resolved as part of gomod.ListDependencies. 64 | } 65 | 66 | // Determine the canonical code host of the current repository 67 | repoRepoRoot, err := vcs.RepoRootForImportPath(repo, false) 68 | if err != nil { 69 | help := "Make sure your git repo has a remote (git remote add origin git@github.com:owner/repo)" 70 | return "", false, fmt.Errorf("%v\n\n%s", err, help) 71 | } 72 | 73 | name = repoRepoRoot.Root + suffix 74 | return name, name == "std", nil 75 | } 76 | 77 | // isModule returns true if there is a go.mod file in the given directory. 78 | func isModule(dir string) bool { 79 | _, err := os.Stat(filepath.Join(dir, "go.mod")) 80 | return err == nil 81 | } 82 | -------------------------------------------------------------------------------- /internal/newtypes/newtypes.go: -------------------------------------------------------------------------------- 1 | package newtypes 2 | 3 | import ( 4 | "go/types" 5 | 6 | "golang.org/x/tools/go/packages" 7 | ) 8 | 9 | type PackageID string 10 | 11 | func GetID(pkg *packages.Package) PackageID { 12 | return PackageID(pkg.PkgPath) 13 | } 14 | 15 | func GetFromTypesPackage(tPkg *types.Package) PackageID { 16 | return PackageID(tPkg.Path()) 17 | } 18 | -------------------------------------------------------------------------------- /internal/output/duration.go: -------------------------------------------------------------------------------- 1 | package output 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | var durations = []time.Duration{ 8 | time.Nanosecond, 9 | time.Microsecond, 10 | time.Millisecond, 11 | time.Second, 12 | time.Minute, 13 | time.Hour, 14 | } 15 | 16 | // HumanElapsed returns the time elapsed since the given start time truncated 17 | // to 100x the highest non-zero duration unit (ns, us, ms, ...). This tends to 18 | // create very short duration strings when printed (e.g. 725.8ms) without having 19 | // to fiddle too much with 20 | func HumanElapsed(start time.Time) time.Duration { 21 | return humanElapsed(time.Since(start)) 22 | } 23 | 24 | func humanElapsed(elapsed time.Duration) time.Duration { 25 | i := 0 26 | for i < len(durations) && elapsed >= durations[i] { 27 | i++ 28 | } 29 | 30 | if i >= 2 { 31 | // Truncate to the next duration unit 32 | resolution := durations[i-2] 33 | 34 | if (durations[i-1] / durations[i-2]) > 100 { 35 | // If we're going from ns -> us, us -> ms, ms -> s, 36 | // then we want to have two decimal points of precision 37 | // here. Not doing this for s -> m or m -> h is fine as 38 | // there will already be this much precision. 39 | resolution *= 10 40 | } 41 | 42 | return elapsed.Truncate(resolution) 43 | } 44 | 45 | return elapsed 46 | } 47 | -------------------------------------------------------------------------------- /internal/output/duration_test.go: -------------------------------------------------------------------------------- 1 | package output 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | ) 7 | 8 | func TestHumanElapsed(t *testing.T) { 9 | testCases := []struct { 10 | input time.Duration 11 | expected time.Duration 12 | }{ 13 | { 14 | input: time.Nanosecond * 123, 15 | expected: time.Nanosecond * 123, 16 | }, 17 | 18 | { 19 | input: time.Microsecond*5 + time.Nanosecond*123, 20 | expected: time.Microsecond*5 + time.Nanosecond*120, 21 | }, 22 | { 23 | input: time.Millisecond*5 + time.Microsecond*123 + time.Nanosecond*123, 24 | expected: time.Millisecond*5 + time.Microsecond*120, 25 | }, 26 | { 27 | input: time.Second*5 + time.Millisecond*123 + time.Microsecond*123, 28 | expected: time.Second*5 + time.Millisecond*120, 29 | }, 30 | { 31 | input: time.Minute*5 + time.Second*12 + time.Millisecond*123, 32 | expected: time.Minute*5 + time.Second*12, 33 | }, 34 | { 35 | input: time.Hour*5 + time.Minute*12 + time.Second*12, 36 | expected: time.Hour*5 + time.Minute*12, 37 | }, 38 | } 39 | 40 | for _, testCase := range testCases { 41 | if actual := humanElapsed(testCase.input); actual != testCase.expected { 42 | t.Errorf("unexpected duration for %s. want=%q have=%q", testCase.input, testCase.expected, actual) 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /internal/output/output.go: -------------------------------------------------------------------------------- 1 | package output 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | "sync/atomic" 7 | "time" 8 | 9 | "github.com/charmbracelet/log" 10 | "github.com/efritz/pentimento" 11 | "github.com/weightylarva/scip-go/internal/parallel" 12 | ) 13 | 14 | type Verbosity int 15 | 16 | const ( 17 | NoOutput Verbosity = iota 18 | DefaultOutput 19 | VerboseOutput 20 | VeryVerboseOutput 21 | VeryVeryVerboseOutput 22 | ) 23 | 24 | type Options struct { 25 | Verbosity Verbosity 26 | ShowAnimations bool 27 | } 28 | 29 | var opts Options = Options{ 30 | Verbosity: DefaultOutput, 31 | ShowAnimations: false, 32 | } 33 | 34 | // updateInterval is the duration between updates in withProgress. 35 | var updateInterval = time.Second / 4 36 | 37 | // ticker is the animated throbber used in printProgress. 38 | var ticker = pentimento.NewAnimatedString([]string{ 39 | "⠸", "⠼", 40 | "⠴", "⠦", 41 | "⠧", "⠇", 42 | "⠏", "⠋", 43 | "⠙", "⠹", 44 | }, updateInterval) 45 | 46 | var successPrefix = "✔" 47 | 48 | // WithProgress prints a spinner while the given function is active. 49 | func WithProgress(name string, fn func() error) error { 50 | ch := make(chan func() error, 1) 51 | ch <- fn 52 | close(ch) 53 | 54 | wg, errCh, count := parallel.Run(ch) 55 | WithProgressParallel(wg, name, count, 1) 56 | 57 | // Handle any associated errors 58 | select { 59 | case err := <-errCh: 60 | return err 61 | default: 62 | return nil 63 | } 64 | } 65 | 66 | // WithProgressParallel will continuously print progress to stdout until the given wait group 67 | // counter goes to zero. Progress is determined by the values of `c` (number of tasks completed) 68 | // and the value `n` (total number of tasks). 69 | func WithProgressParallel(wg *sync.WaitGroup, name string, c *uint64, n uint64) { 70 | sync := make(chan struct{}) 71 | go func() { 72 | wg.Wait() 73 | close(sync) 74 | }() 75 | 76 | withTitle(name, func(printer *pentimento.Printer) { 77 | for { 78 | select { 79 | case <-sync: 80 | return 81 | case <-time.After(updateInterval): 82 | } 83 | 84 | printProgress(printer, name, c, n) 85 | } 86 | }) 87 | } 88 | 89 | // withTitle invokes withTitleAnimated withTitleStatic depending on the value of animated. 90 | func withTitle(name string, fn func(printer *pentimento.Printer)) { 91 | if opts.Verbosity == NoOutput { 92 | fn(nil) 93 | } else if !opts.ShowAnimations || opts.Verbosity >= VeryVerboseOutput { 94 | withTitleStatic(name, opts.Verbosity, fn) 95 | } else { 96 | withTitleAnimated(name, opts.Verbosity, fn) 97 | } 98 | } 99 | 100 | // withTitleStatic invokes the given function with non-animated output. 101 | func withTitleStatic(name string, verbosity Verbosity, fn func(printer *pentimento.Printer)) { 102 | start := time.Now() 103 | fmt.Printf("%s\n", name) 104 | fn(nil) 105 | 106 | if verbosity > DefaultOutput { 107 | fmt.Printf("Finished in %s.\n\n", HumanElapsed(start)) 108 | } 109 | } 110 | 111 | // withTitleStatic invokes the given function with animated output. 112 | func withTitleAnimated(name string, verbosity Verbosity, fn func(printer *pentimento.Printer)) { 113 | start := time.Now() 114 | fmt.Printf("%s %s... ", ticker, name) 115 | 116 | _ = pentimento.PrintProgress(func(printer *pentimento.Printer) error { 117 | defer func() { 118 | _ = printer.Reset() 119 | }() 120 | 121 | fn(printer) 122 | return nil 123 | }) 124 | 125 | fmt.Printf("%s %s... Done (%s)\n", successPrefix, name, HumanElapsed(start)) 126 | } 127 | 128 | // printProgress outputs a throbber, the given name, and the given number of tasks completed to 129 | // the given printer. 130 | func printProgress(printer *pentimento.Printer, name string, c *uint64, n uint64) { 131 | if printer == nil { 132 | return 133 | } 134 | 135 | content := pentimento.NewContent() 136 | 137 | if c == nil { 138 | content.AddLine("%s %s...", ticker, name) 139 | } else { 140 | content.AddLine("%s %s... %d/%d\n", ticker, name, atomic.LoadUint64(c), n) 141 | } 142 | 143 | printer.WriteContent(content) 144 | } 145 | 146 | func SetOutputOptions(verb Verbosity, animation bool) { 147 | switch verb { 148 | case NoOutput: 149 | log.SetLevel(log.FatalLevel) 150 | case DefaultOutput: 151 | log.SetLevel(log.WarnLevel) 152 | case VerboseOutput: 153 | log.SetLevel(log.InfoLevel) 154 | case VeryVerboseOutput, VeryVeryVerboseOutput: 155 | log.SetLevel(log.DebugLevel) 156 | } 157 | opts.Verbosity = verb 158 | opts.ShowAnimations = animation 159 | } 160 | 161 | func Logf(format string, a ...any) { 162 | if opts.Verbosity >= VeryVeryVerboseOutput { 163 | log.Printf(format, a...) 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /internal/parallel/parallel.go: -------------------------------------------------------------------------------- 1 | package parallel 2 | 3 | import ( 4 | "runtime" 5 | "sync" 6 | "sync/atomic" 7 | ) 8 | 9 | // Run will run the functions read from the given channel concurrently. This function 10 | // returns a wait group synchronized on the invocation functions, a channel on which any error 11 | // values are written, and a pointer to the number of tasks that have completed, which is 12 | // updated atomically. 13 | func Run(ch <-chan func() error) (*sync.WaitGroup, chan error, *uint64) { 14 | var count uint64 15 | var wg sync.WaitGroup 16 | 17 | maxRoutines := runtime.GOMAXPROCS(0) 18 | errCh := make(chan error, maxRoutines) // each goroutine returns at most one error 19 | for i := 0; i < maxRoutines; i++ { 20 | wg.Add(1) 21 | 22 | go func() { 23 | defer wg.Done() 24 | 25 | for fn := range ch { 26 | err := fn() 27 | if err != nil { 28 | errCh <- err 29 | } 30 | atomic.AddUint64(&count, 1) 31 | } 32 | }() 33 | } 34 | 35 | return &wg, errCh, &count 36 | } 37 | -------------------------------------------------------------------------------- /internal/parallel/parallel_test.go: -------------------------------------------------------------------------------- 1 | package parallel 2 | 3 | import ( 4 | "sync/atomic" 5 | "testing" 6 | "time" 7 | ) 8 | 9 | func TestRun(t *testing.T) { 10 | ch := make(chan func() error, 3) 11 | ch <- func() error { return nil } 12 | ch <- func() error { return nil } 13 | ch <- func() error { return nil } 14 | close(ch) 15 | 16 | wg, _, n := Run(ch) 17 | wg.Wait() 18 | 19 | if *n != 3 { 20 | t.Errorf("unexpected count. want=%d want=%d", 3, *n) 21 | } 22 | } 23 | 24 | func TestRunProgress(t *testing.T) { 25 | sync1 := make(chan struct{}) 26 | sync2 := make(chan struct{}) 27 | sync3 := make(chan struct{}) 28 | 29 | ch := make(chan func() error, 3) 30 | ch <- func() error { <-sync1; return nil } 31 | ch <- func() error { <-sync2; return nil } 32 | ch <- func() error { <-sync3; return nil } 33 | close(ch) 34 | 35 | wg, _, n := Run(ch) 36 | 37 | checkValue := func(expected uint64) { 38 | var v uint64 39 | 40 | for i := 0; i < 10; i++ { 41 | if v = atomic.LoadUint64(n); v == expected { 42 | return 43 | } 44 | 45 | <-time.After(time.Millisecond) 46 | } 47 | 48 | t.Fatalf("unexpected progress value. want=%d have=%d", expected, v) 49 | } 50 | 51 | checkValue(0) 52 | close(sync1) 53 | checkValue(1) 54 | close(sync2) 55 | checkValue(2) 56 | close(sync3) 57 | checkValue(3) 58 | wg.Wait() 59 | } 60 | -------------------------------------------------------------------------------- /internal/symbols/symbols.go: -------------------------------------------------------------------------------- 1 | package symbols 2 | 3 | import ( 4 | "fmt" 5 | "go/token" 6 | 7 | "github.com/sourcegraph/scip/bindings/go/scip" 8 | "golang.org/x/tools/go/packages" 9 | ) 10 | 11 | func FromDescriptors(pkg *packages.Package, descriptors ...*scip.Descriptor) string { 12 | if pkg.Module == nil { 13 | panic(fmt.Sprintf("Failed to find package for: %+v\n", pkg.PkgPath)) 14 | } 15 | 16 | return scip.VerboseSymbolFormatter.FormatSymbol(&scip.Symbol{ 17 | Scheme: "scip-go", 18 | Package: &scip.Package{ 19 | Manager: "gomod", 20 | Name: pkg.Module.Path, 21 | Version: pkg.Module.Version, 22 | }, 23 | Descriptors: descriptors, 24 | }) 25 | } 26 | 27 | func RangeFromName(position token.Position, name string, adjust bool) []int32 { 28 | var adjustment int32 = 0 29 | if adjust { 30 | adjustment = 1 31 | } 32 | 33 | line := int32(position.Line - 1) 34 | column := int32(position.Column - 1) 35 | n := int32(len(name)) 36 | 37 | return []int32{line, column + adjustment, column + n + adjustment} 38 | } 39 | 40 | func FormatCode(v string) string { 41 | if v == "" { 42 | return "" 43 | } 44 | 45 | return fmt.Sprintf("```go\n%s\n```", v) 46 | } 47 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/alias/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Check that we don't panic 4 | // Copied from https://github.com/golang/go/issues/68877#issuecomment-2290000187 5 | type ( 6 | T struct{} 7 | U = T 8 | V = U 9 | S U 10 | Z int32 11 | ) 12 | 13 | func f(u U) {} 14 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/embedded/embedded.go: -------------------------------------------------------------------------------- 1 | package embedded 2 | 3 | import ( 4 | "fmt" 5 | "os/exec" 6 | ) 7 | 8 | type osExecCommand struct { 9 | *exec.Cmd 10 | } 11 | 12 | func wrapExecCommand(c *exec.Cmd) { 13 | _ = &osExecCommand{Cmd: c} 14 | } 15 | 16 | type Inner struct { 17 | X int 18 | Y int 19 | Z int 20 | } 21 | 22 | type Outer struct { 23 | Inner 24 | W int 25 | } 26 | 27 | func useOfCompositeStructs() { 28 | o := Outer{ 29 | Inner: Inner{ 30 | X: 1, 31 | Y: 2, 32 | Z: 3, 33 | }, 34 | W: 4, 35 | } 36 | 37 | fmt.Printf("> %d\n", o.X) 38 | fmt.Println(o.Inner.Y) 39 | } 40 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/embedded/go.mod: -------------------------------------------------------------------------------- 1 | module sg/embedded 2 | 3 | go 1.19 4 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/embedded/internal/nested.go: -------------------------------------------------------------------------------- 1 | package nested_internal 2 | 3 | import ( 4 | "fmt" 5 | "sg/embedded" 6 | ) 7 | 8 | func Something(recent embedded.RecentCommittersResults) { 9 | for _, commit := range recent.Nodes { 10 | for _, author := range commit.Authors.Nodes { 11 | fmt.Println(author.Name) 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/embedded/nested.go: -------------------------------------------------------------------------------- 1 | package embedded 2 | 3 | import "net/http" 4 | 5 | type NestedHandler struct { 6 | http.Handler 7 | 8 | // Wow, a great thing for integers 9 | Other int 10 | } 11 | 12 | func NestedExample(n NestedHandler) { 13 | _ = n.Handler.ServeHTTP 14 | _ = n.ServeHTTP 15 | _ = n.Other 16 | } 17 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/embedded/something.go: -------------------------------------------------------------------------------- 1 | package embedded 2 | 3 | import "fmt" 4 | 5 | type RecentCommittersResults struct { 6 | Nodes []struct { 7 | Authors struct { 8 | Nodes []struct { 9 | Date string 10 | Email string 11 | Name string 12 | User struct { 13 | Login string 14 | } 15 | AvatarURL string 16 | } 17 | } 18 | } 19 | PageInfo struct { 20 | HasNextPage bool 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/generallyeric/generallyeric.go: -------------------------------------------------------------------------------- 1 | // generallyeric -> generic for short 2 | package generallyeric 3 | 4 | import "fmt" 5 | 6 | func Print[T any](s []T) { 7 | for _, v := range s { 8 | fmt.Print(v) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/generallyeric/go.mod: -------------------------------------------------------------------------------- 1 | module sg/generallyeric 2 | 3 | go 1.19 4 | 5 | require golang.org/x/exp v0.0.0-20221205204356-47842c84f3db 6 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/generallyeric/go.sum: -------------------------------------------------------------------------------- 1 | golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o= 2 | golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= 3 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/generallyeric/new_operators.go: -------------------------------------------------------------------------------- 1 | package generallyeric 2 | 3 | import "golang.org/x/exp/constraints" 4 | 5 | type Number interface { 6 | constraints.Float | constraints.Integer | constraints.Complex 7 | } 8 | 9 | func Double[T Number](value T) T { 10 | return value * 2 11 | } 12 | 13 | type Box[T any] struct { 14 | Something T 15 | } 16 | 17 | type handler[T any] struct { 18 | Box[T] 19 | Another string 20 | } 21 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/generallyeric/person.go: -------------------------------------------------------------------------------- 1 | package generallyeric 2 | 3 | import "fmt" 4 | 5 | type Person interface { 6 | Work() 7 | } 8 | 9 | type worker string 10 | 11 | func (w worker) Work() { 12 | fmt.Printf("%s is working\n", w) 13 | } 14 | 15 | func DoWork[T Person](things []T) { 16 | for _, v := range things { 17 | v.Work() 18 | } 19 | } 20 | 21 | func main() { 22 | var a, b, c worker 23 | a = "A" 24 | b = "B" 25 | c = "C" 26 | DoWork([]worker{a, b, c}) 27 | } 28 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/impls/go.mod: -------------------------------------------------------------------------------- 1 | module sg/impls 2 | 3 | go 1.19 4 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/impls/impls.go: -------------------------------------------------------------------------------- 1 | package impls 2 | 3 | type I1 interface { 4 | F1() 5 | } 6 | 7 | type I1Clone interface { 8 | F1() 9 | } 10 | 11 | type IfaceOther interface { 12 | Something() 13 | Another() 14 | } 15 | 16 | type T1 int 17 | 18 | func (r T1) F1() {} 19 | 20 | type T2 int 21 | 22 | func (r T2) F1() {} 23 | func (r T2) F2() {} 24 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/impls/remote_impls.go: -------------------------------------------------------------------------------- 1 | package impls 2 | 3 | import "net/http" 4 | 5 | func Something(r http.ResponseWriter) {} 6 | 7 | type MyWriter struct{} 8 | 9 | func (w MyWriter) Header() http.Header { panic("") } 10 | func (w MyWriter) Write([]byte) (int, error) { panic("") } 11 | func (w MyWriter) WriteHeader(statusCode int) { panic("") } 12 | 13 | func Another() { 14 | Something(MyWriter{}) 15 | } 16 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/initial/builtin_types.go: -------------------------------------------------------------------------------- 1 | package initial 2 | 3 | func UsesBuiltin() int { 4 | var x int = 5 5 | return x 6 | } 7 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/initial/child_symbols.go: -------------------------------------------------------------------------------- 1 | package initial 2 | 3 | // Const is a constant equal to 5. It's the best constant I've ever written. 😹 4 | const Const = 5 5 | 6 | // Docs for the const block itself. 7 | const ( 8 | // ConstBlock1 is a constant in a block. 9 | ConstBlock1 = 1 10 | 11 | // ConstBlock2 is a constant in a block. 12 | ConstBlock2 = 2 13 | ) 14 | 15 | // Var is a variable interface. 16 | var Var Interface = &Struct{Field: "bar!"} 17 | 18 | // unexportedVar is an unexported variable interface. 19 | var unexportedVar Interface = &Struct{Field: "bar!"} 20 | 21 | // x has a builtin error type 22 | var x error 23 | 24 | var BigVar Interface = &Struct{ 25 | Field: "bar!", 26 | Anonymous: struct { 27 | FieldA int 28 | FieldB int 29 | FieldC int 30 | }{FieldA: 1337}, 31 | } 32 | 33 | // What are docs, really? 34 | // I can't say for sure, I don't write any. 35 | // But look, a CAT! 36 | // 37 | // |\ _,,,---,,_ 38 | // ZZZzz /,`.-'`' -. ;-;;,_ 39 | // |,4- ) )-,_. ,\ ( `'-' 40 | // '---''(_/--' `-'\_) 41 | // 42 | // It's sleeping! Some people write that as `sleeping` but Markdown 43 | // isn't allowed in Go docstrings, right? right?! 44 | var ( 45 | // This has some docs 46 | VarBlock1 = "if you're reading this" 47 | 48 | VarBlock2 = "hi" 49 | ) 50 | 51 | // Embedded is a struct, to be embedded in another struct. 52 | type Embedded struct { 53 | // EmbeddedField has some docs! 54 | EmbeddedField string 55 | Field string // conflicts with parent "Field" 56 | } 57 | 58 | type Struct struct { 59 | *Embedded 60 | Field string 61 | Anonymous struct { 62 | FieldA int 63 | FieldB int 64 | FieldC int 65 | } 66 | } 67 | 68 | // StructMethod has some docs! 69 | func (s *Struct) StructMethod() {} 70 | 71 | func (s *Struct) ImplementsInterface() string { return "hi!" } 72 | 73 | func (s *Struct) MachineLearning( 74 | param1 float32, // It's ML, I can't describe what this param is. 75 | 76 | // We call the below hyperparameters because, uhh, well: 77 | // 78 | // ,-. _,---._ __ / \ 79 | // / ) .-' `./ / \ 80 | // ( ( ,' `/ /| 81 | // \ `-" \'\ / | 82 | // `. , \ \ / | 83 | // /`. ,'-`----Y | 84 | // ( ; | ' 85 | // | ,-. ,-' | / 86 | // | | ( | hjw | / 87 | // ) | \ `.___________|/ 88 | // `--' `--' 89 | // 90 | hyperparam2 float32, 91 | hyperparam3 float32, 92 | ) float32 { 93 | // varShouldNotHaveDocs is in a function, should not have docs emitted. 94 | var varShouldNotHaveDocs int32 95 | 96 | // constShouldNotHaveDocs is in a function, should not have docs emitted. 97 | const constShouldNotHaveDocs = 5 98 | 99 | // typeShouldNotHaveDocs is in a function, should not have docs emitted. 100 | type typeShouldNotHaveDocs struct{ a string } 101 | 102 | // funcShouldNotHaveDocs is in a function, should not have docs emitted. 103 | funcShouldNotHaveDocs := func(a string) string { return "hello" } 104 | 105 | return param1 + (hyperparam2 * *hyperparam3) // lol is this all ML is? I'm gonna be rich 106 | } 107 | 108 | // Interface has docs too 109 | type Interface interface { 110 | ImplementsInterface() string 111 | } 112 | 113 | func NewInterface() Interface { return nil } 114 | 115 | var SortExportedFirst = 1 116 | 117 | var sortUnexportedSecond = 2 118 | 119 | var _sortUnderscoreLast = 3 120 | 121 | // Yeah this is some Go magic incantation which is common. 122 | // 123 | // ,_ _ 124 | // |\\_,-~/ 125 | // / _ _ | ,--. 126 | // ( @ @ ) / ,-' 127 | // \ _T_/-._( ( 128 | // / `. \ 129 | // | _ \ | 130 | // \ \ , / | 131 | // || |-_\__ / 132 | // ((_/`(____,-' 133 | var _ = Interface(&Struct{}) 134 | 135 | type _ = struct{} 136 | 137 | // crypto/tls/common_string.go uses this pattern.. 138 | func _() { 139 | } 140 | 141 | // Go can be fun 142 | type ( 143 | // And confusing 144 | X struct { 145 | bar string 146 | } 147 | 148 | Y struct { 149 | baz float64 150 | } 151 | ) 152 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/initial/func_declarations.go: -------------------------------------------------------------------------------- 1 | package initial 2 | 3 | func UsesLater() { 4 | DefinedLater() 5 | } 6 | 7 | func DefinedLater() {} 8 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/initial/go.mod: -------------------------------------------------------------------------------- 1 | module sg/initial 2 | 3 | go 1.23 4 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/initial/methods_and_receivers.go: -------------------------------------------------------------------------------- 1 | package initial 2 | 3 | import "fmt" 4 | 5 | type MyStruct struct{ f, y int } 6 | 7 | func (m MyStruct) RecvFunction(b int) int { return m.f + b } 8 | 9 | func SomethingElse() { 10 | s := MyStruct{f: 0} 11 | fmt.Println(s) 12 | } 13 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/initial/package_definition.go: -------------------------------------------------------------------------------- 1 | // This is a module for testing purposes. 2 | // This should now be the place that has a definition 3 | package initial 4 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/initial/rangefunc.go: -------------------------------------------------------------------------------- 1 | package initial 2 | 3 | import ( 4 | "slices" 5 | ) 6 | 7 | func f(xs []int) int { 8 | for _, x := range slices.All(xs) { 9 | return x 10 | } 11 | return -1 12 | } 13 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/initial/toplevel_decls.go: -------------------------------------------------------------------------------- 1 | package initial 2 | 3 | const MY_THING = 10 4 | const OTHER_THING = MY_THING 5 | 6 | func usesMyThing() { 7 | _ = MY_THING 8 | } 9 | 10 | var initFunctions = map[string]int{} 11 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/initial/type_declarations.go: -------------------------------------------------------------------------------- 1 | package initial 2 | 3 | type LiteralType int 4 | 5 | type FuncType func(LiteralType, int) bool 6 | 7 | type IfaceType interface { 8 | Method() LiteralType 9 | } 10 | 11 | type StructType struct { 12 | m IfaceType 13 | f LiteralType 14 | 15 | // anonymous struct 16 | anon struct { 17 | sub int 18 | } 19 | 20 | // interface within struct 21 | i interface { 22 | AnonMethod() bool 23 | } 24 | } 25 | 26 | type DeclaredBefore struct{ DeclaredAfter } 27 | type DeclaredAfter struct{} 28 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/initial/type_hovers.go: -------------------------------------------------------------------------------- 1 | package initial 2 | 3 | type ( 4 | // HoverTypeList is a cool struct 5 | HoverTypeList struct{} 6 | ) 7 | 8 | // This should show up as well 9 | type HoverType struct{} 10 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/inlinestruct/go.mod: -------------------------------------------------------------------------------- 1 | module sg/inlinestruct 2 | 3 | go 1.19 4 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/inlinestruct/inlinestruct.go: -------------------------------------------------------------------------------- 1 | package inlinestruct 2 | 3 | type FieldInterface interface { 4 | SomeMethod() string 5 | } 6 | 7 | var MyInline = struct { 8 | privateField FieldInterface 9 | PublicField FieldInterface 10 | }{} 11 | 12 | func MyFunc() { 13 | _ = MyInline.privateField 14 | _ = MyInline.PublicField 15 | } 16 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/inlinestruct/inlinestruct_func.go: -------------------------------------------------------------------------------- 1 | package inlinestruct 2 | 3 | type InFuncSig struct { 4 | value bool 5 | } 6 | 7 | var rowsCloseHook = func() func(InFuncSig, *error) { return nil } 8 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/inlinestruct/inlinestruct_genericindex.go: -------------------------------------------------------------------------------- 1 | package inlinestruct 2 | 3 | type Processor[T any] interface { 4 | Process(payload T) 5 | ProcessorType() string 6 | } 7 | 8 | type Limit int 9 | 10 | type ProcessImpl struct{} 11 | 12 | func (p *ProcessImpl) Process(payload Limit) { panic("not implemented") } 13 | func (p *ProcessImpl) ProcessorType() string { panic("not implemented") } 14 | 15 | var _ Processor[Limit] = &ProcessImpl{} 16 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/inlinestruct/inlinestruct_interface.go: -------------------------------------------------------------------------------- 1 | package inlinestruct 2 | 3 | import "context" 4 | 5 | func Target() interface { 6 | OID(context.Context) (int, error) 7 | AbbreviatedOID(context.Context) (string, error) 8 | Commit(context.Context) (string, error) 9 | Type(context.Context) (int, error) 10 | } { 11 | panic("not implemented") 12 | } 13 | 14 | func something() { 15 | x := Target() 16 | x.OID(context.Background()) 17 | } 18 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/inlinestruct/inlinestruct_map.go: -------------------------------------------------------------------------------- 1 | package inlinestruct 2 | 3 | var testHook = func(map[string]string) {} 4 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/inlinestruct/inlinestruct_multivar.go: -------------------------------------------------------------------------------- 1 | package inlinestruct 2 | 3 | type Params struct{} 4 | type HighlightedCode struct{} 5 | 6 | var Mocks, emptyMocks struct { 7 | Code func(p Params) (response *HighlightedCode, aborted bool, err error) 8 | } 9 | 10 | var MocksSingle struct { 11 | Code func(p Params) (response *HighlightedCode, aborted bool, err error) 12 | } 13 | 14 | var ( 15 | okReply interface{} = "OK" 16 | pongReply interface{} = "PONG" 17 | ) 18 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/package-documentation/primary.go: -------------------------------------------------------------------------------- 1 | // This is documentation for this package. 2 | package packagedocumentation 3 | 4 | func Exported() {} 5 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/package-documentation/secondary.go: -------------------------------------------------------------------------------- 1 | package packagedocumentation 2 | 3 | func AlsoExporter() {} 4 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/replace-directives/go.mod: -------------------------------------------------------------------------------- 1 | module sg/replace-directives 2 | 3 | go 1.19 4 | 5 | 6 | require ( 7 | github.com/dghubble/gologin v2.2.0+incompatible 8 | ) 9 | 10 | replace ( 11 | github.com/dghubble/gologin => github.com/sourcegraph/gologin v1.0.2-0.20181110030308-c6f1b62954d8 12 | ) 13 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/replace-directives/go.sum: -------------------------------------------------------------------------------- 1 | github.com/sourcegraph/gologin v1.0.2-0.20181110030308-c6f1b62954d8 h1:K7hzuWsJGoU8ILHJzrXxsuvXvLHpP/g4iUk7VFj2lY8= 2 | github.com/sourcegraph/gologin v1.0.2-0.20181110030308-c6f1b62954d8/go.mod h1:0VfoEApmSPgPhnePllwhrB4vwCUkI0K0w8aueOgoJQI= 3 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/replace-directives/replace_directives.go: -------------------------------------------------------------------------------- 1 | package replacers 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/dghubble/gologin" 7 | ) 8 | 9 | func Something() { 10 | fmt.Println(gologin.DefaultCookieConfig) 11 | } 12 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/sharedtestmodule/cmd/gitserver/server/cleanup.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | func LiterallyAnything() {} 4 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/sharedtestmodule/cmd/gitserver/server/cleanup_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import "testing" 4 | 5 | func TestStuff(t *testing.T) { 6 | wd := "hello" 7 | repo := "world" 8 | 9 | runCmd(t, wd, "git", "init", repo) 10 | } 11 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/sharedtestmodule/cmd/gitserver/server/server.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | func AnythingAtAll() {} 4 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/sharedtestmodule/cmd/gitserver/server/server_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import "testing" 4 | 5 | func TestExecRequest(t *testing.T) { 6 | t.Log("hello world") 7 | } 8 | 9 | func runCmd(t *testing.T, dir string, cmd string, arg ...string) {} 10 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/sharedtestmodule/go.mod: -------------------------------------------------------------------------------- 1 | module sg/sharedtestmodule 2 | 3 | go 1.19 4 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/switches/go.mod: -------------------------------------------------------------------------------- 1 | module sg/switches 2 | 3 | go 1.19 4 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/switches/switches.go: -------------------------------------------------------------------------------- 1 | package switches 2 | 3 | // CustomSwitch does the things in a switch 4 | type CustomSwitch struct{} 5 | 6 | // Something does some things... and stuff 7 | func (c *CustomSwitch) Something() bool { return false } 8 | 9 | func Switch(interfaceValue interface{}) bool { 10 | switch concreteValue := interfaceValue.(type) { 11 | case int: 12 | return concreteValue*3 > 10 13 | case bool: 14 | return !concreteValue 15 | case CustomSwitch: 16 | return concreteValue.Something() 17 | default: 18 | return false 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testdata/anonymous_structs.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import "fmt" 4 | 5 | type TypeContainingAnonymousStructs struct { 6 | a, b struct { 7 | x int 8 | y string 9 | } 10 | c struct { 11 | X int 12 | Y string 13 | } 14 | } 15 | 16 | func funcContainingAnonymousStructs() { 17 | d := struct { 18 | x int 19 | y string 20 | }{ 21 | x: 1, 22 | y: "one", 23 | } 24 | 25 | var e struct { 26 | x int 27 | y string 28 | } 29 | 30 | e.x = 2 31 | e.y = "two" 32 | 33 | var f TypeContainingAnonymousStructs 34 | f.a.x = 3 35 | f.a.y = "three" 36 | f.b.x = 4 37 | f.b.y = "four" 38 | f.c.X = 5 39 | f.c.Y = "five" 40 | 41 | fmt.Printf("> %s, %s\n", d.x, d.y) 42 | fmt.Printf("> %s, %s\n", e.x, e.y) 43 | 44 | fmt.Printf("> %s, %s\n", f.a.x, f.a.y) 45 | fmt.Printf("> %s, %s\n", f.b.x, f.b.y) 46 | fmt.Printf("> %s, %s\n", f.c.X, f.c.Y) 47 | } 48 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testdata/cmd/minimal_main/minimal_main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type User struct { 4 | Id, Name string 5 | } 6 | 7 | type UserResource struct{} 8 | 9 | func main() {} 10 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testdata/conflicting_test_symbols/sandbox_unsupported.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !darwin 2 | // +build !linux,!darwin 3 | 4 | // From https://github.com/moby/moby/blob/master/libnetwork/osl/sandbox_unsupported.go 5 | 6 | package osl 7 | 8 | import "errors" 9 | 10 | var ( 11 | // ErrNotImplemented is for platforms which don't implement sandbox 12 | ErrNotImplemented = errors.New("not implemented") 13 | ) 14 | 15 | // NewSandbox provides a new sandbox instance created in an os specific way 16 | // provided a key which uniquely identifies the sandbox 17 | func NewSandbox(key string, osCreate, isRestore bool) (*string, error) { 18 | return nil, ErrNotImplemented 19 | } 20 | 21 | // GenerateKey generates a sandbox key based on the passed 22 | // container id. 23 | func GenerateKey(containerID string) string { 24 | return "" 25 | } 26 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testdata/conflicting_test_symbols/sandbox_unsupported_test.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !windows && !freebsd 2 | // +build !linux,!windows,!freebsd 3 | 4 | package osl 5 | 6 | import ( 7 | "errors" 8 | "testing" 9 | ) 10 | 11 | var ErrNotImplemented = errors.New("not implemented") 12 | 13 | func newKey(t *testing.T) (string, error) { 14 | return "", ErrNotImplemented 15 | } 16 | 17 | func verifySandbox(t *testing.T, s string) { 18 | return 19 | } 20 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testdata/data.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | "context" 5 | 6 | "sg/testdata/internal/secret" 7 | ) 8 | 9 | // TestInterface is an interface used for testing. 10 | type TestInterface interface { 11 | // Do does a test thing. 12 | Do(ctx context.Context, data string) (score int, _ error) 13 | } 14 | 15 | type ( 16 | // TestStruct is a struct used for testing. 17 | TestStruct struct { 18 | // SimpleA docs 19 | SimpleA int 20 | // SimpleB docs 21 | SimpleB int 22 | // SimpleC docs 23 | SimpleC int 24 | 25 | FieldWithTag string `json:"tag"` 26 | FieldWithAnonymousType struct { 27 | NestedA string 28 | NestedB string 29 | // NestedC docs 30 | NestedC string 31 | } 32 | 33 | EmptyStructField struct{} 34 | } 35 | 36 | TestEmptyStruct struct{} 37 | ) 38 | 39 | // Score is just a hardcoded number. 40 | const Score = uint64(42) 41 | const secretScore = secret.SecretScore 42 | 43 | const SomeString = "foobar" 44 | const LongString = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tincidunt viverra aliquam. Phasellus finibus, arcu eu commodo porta, dui quam dictum ante, nec porta enim leo quis felis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Curabitur luctus orci tortor, non condimentum arcu bibendum ut. Proin sit amet vulputate lorem, ut egestas arcu. Curabitur quis sagittis mi. Aenean elit sem, imperdiet ut risus eget, varius varius erat.\nNullam lobortis tortor sed sodales consectetur. Aenean condimentum vehicula elit, eget interdum ante finibus nec. Mauris mollis, nulla eu vehicula rhoncus, eros lectus viverra tellus, ac hendrerit quam massa et felis. Nunc vestibulum diam a facilisis sollicitudin. Aenean nec varius metus. Sed nec diam nibh. Ut erat erat, suscipit et ante eget, tincidunt condimentum orci. Aenean nec facilisis augue, ac sodales ex. Nulla dictum hendrerit tempus. Aliquam fringilla tortor in massa molestie, quis bibendum nulla ullamcorper. Suspendisse congue laoreet elit, vitae consectetur orci facilisis non. Aliquam tempus ultricies sapien, rhoncus tincidunt nisl tincidunt eget. Aliquam nisi ante, rutrum eget viverra imperdiet, congue ut nunc. Donec mollis sed tellus vel placerat. Sed mi ex, fringilla a fermentum a, tincidunt eget lectus.\nPellentesque lacus nibh, accumsan eget feugiat nec, gravida eget urna. Donec quam velit, imperdiet in consequat eget, ultricies eget nunc. Curabitur interdum vel sem et euismod. Donec sed vulputate odio, sit amet bibendum tellus. Integer pellentesque nunc eu turpis cursus, vestibulum sodales ipsum posuere. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Ut at vestibulum sapien. In hac habitasse platea dictumst. Nullam sed lobortis urna, non bibendum ipsum. Sed in sapien quis purus semper fringilla. Integer ut egestas nulla, eu ornare lectus. Maecenas quis sapien condimentum, dignissim urna quis, hendrerit neque. Donec cursus sit amet metus eu mollis.\nSed scelerisque vitae odio non egestas. Cras hendrerit tortor mauris. Aenean quis imperdiet nulla, a viverra purus. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Praesent finibus faucibus orci, sed ultrices justo iaculis ut. Ut libero massa, condimentum at elit non, fringilla iaculis quam. Sed sit amet ipsum placerat, tincidunt sem in, efficitur lacus. Curabitur ligula orci, tempus ut magna eget, sodales tristique odio.\nPellentesque in libero ac risus pretium ultrices. In hac habitasse platea dictumst. Curabitur a quam sed orci tempus luctus. Integer commodo nec odio quis consequat. Aenean vitae dapibus augue, nec dictum lectus. Etiam sit amet leo diam. Duis eu ligula venenatis, fermentum lacus vel, interdum odio. Vivamus sit amet libero vitae elit interdum cursus et eu erat. Cras interdum augue sit amet ex aliquet tempor. Praesent dolor nisl, convallis bibendum mauris a, euismod commodo ante. Phasellus non ipsum condimentum, molestie dolor quis, pretium nisi. Mauris augue urna, fermentum ut lacinia a, efficitur vitae odio. Praesent finibus nisl et dolor luctus faucibus. Donec eget lectus sed mi porttitor placerat ac eu odio." 45 | const ConstMath = 1 + (2+3)*5 46 | 47 | type StringAlias string 48 | 49 | const AliasedString StringAlias = "foobar" 50 | 51 | // Doer is similar to the test interface (but not the same). 52 | func (ts *TestStruct) Doer(ctx context.Context, data string) (score int, err error) { 53 | return Score, nil 54 | } 55 | 56 | // StructTagRegression is a struct that caused panic in the wild. Added here to 57 | // support a regression test. 58 | // 59 | // See https://github.com/tal-tech/go-zero/blob/11dd3d75ecceaa3f5772024fb3f26dec1ada8e9c/core/mapping/unmarshaler_test.go#L2272. 60 | type StructTagRegression struct { 61 | Value int `key:",range=[:}"` 62 | } 63 | 64 | type TestEqualsStruct = struct { 65 | Value int 66 | } 67 | 68 | type ShellStruct struct { 69 | // Ensure this field comes before the definition 70 | // so that we grab the correct one in our unit 71 | // tests. 72 | InnerStruct 73 | } 74 | 75 | type InnerStruct struct{} 76 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testdata/duplicate_path_id/main.go: -------------------------------------------------------------------------------- 1 | package gosrc 2 | 3 | type importMeta struct{} 4 | 5 | type sourceMeta struct{} 6 | 7 | func fetchMeta() (string, *importMeta, *sourceMeta) { 8 | panic("hmm") 9 | } 10 | 11 | func init() {} 12 | func init() {} 13 | func init() {} 14 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testdata/duplicate_path_id/two.go: -------------------------------------------------------------------------------- 1 | package gosrc 2 | 3 | func init() {} 4 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testdata/external_composite.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import "net/http" 4 | 5 | type NestedHandler struct { 6 | http.Handler 7 | Other int 8 | } 9 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testdata/go.mod: -------------------------------------------------------------------------------- 1 | module sg/testdata 2 | 3 | go 1.19 4 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testdata/implementations.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | type I0 interface{} 4 | 5 | type I1 interface { 6 | F1() 7 | } 8 | 9 | type I2 interface { 10 | F2() 11 | } 12 | 13 | type T1 int 14 | 15 | func (r T1) F1() {} 16 | 17 | type T2 int 18 | 19 | func (r T2) F1() {} 20 | func (r T2) F2() {} 21 | 22 | type A1 = T1 23 | type A12 = A1 24 | 25 | type InterfaceWithNonExportedMethod interface { 26 | nonExportedMethod() 27 | } 28 | 29 | type InterfaceWithExportedMethod interface { 30 | ExportedMethod() 31 | } 32 | 33 | type Foo int 34 | 35 | func (r Foo) nonExportedMethod() {} 36 | func (r Foo) ExportedMethod() {} 37 | func (r Foo) Close() error { return nil } 38 | 39 | type SharedOne interface { 40 | Shared() 41 | Distinct() 42 | } 43 | 44 | type SharedTwo interface { 45 | Shared() 46 | Unique() 47 | } 48 | 49 | type Between struct{} 50 | 51 | func (Between) Shared() {} 52 | func (Between) Distinct() {} 53 | func (Between) Unique() {} 54 | 55 | func shouldShow(shared SharedOne) { 56 | shared.Shared() 57 | } 58 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testdata/implementations_embedded.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import "io" 4 | 5 | type I3 interface { 6 | Close() error 7 | } 8 | 9 | type TClose struct { 10 | io.Closer 11 | } 12 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testdata/implementations_methods.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | type InterfaceWithSingleMethod interface { 4 | SingleMethod() float64 5 | } 6 | 7 | type StructWithMethods struct{} 8 | 9 | func (StructWithMethods) SingleMethod() float64 { return 5.0 } 10 | 11 | type InterfaceWithSingleMethodTwoImplementers interface { 12 | SingleMethodTwoImpl() float64 13 | } 14 | 15 | type TwoImplOne struct{} 16 | 17 | func (TwoImplOne) SingleMethodTwoImpl() float64 { return 5.0 } 18 | 19 | type TwoImplTwo struct{} 20 | 21 | func (TwoImplTwo) SingleMethodTwoImpl() float64 { return 5.0 } 22 | func (TwoImplTwo) RandomThingThatDoesntMatter() float64 { return 5.0 } 23 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testdata/implementations_remote.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import "net/http" 4 | 5 | type implementsWriter struct{} 6 | 7 | func (implementsWriter) Header() http.Header { panic("Just for how") } 8 | func (implementsWriter) Write([]byte) (int, error) { panic("Just for show") } 9 | func (implementsWriter) WriteHeader(statusCode int) {} 10 | 11 | func ShowsInSignature(respWriter http.ResponseWriter) { 12 | respWriter.WriteHeader(1) 13 | } 14 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testdata/internal/secret/doc.go: -------------------------------------------------------------------------------- 1 | // secret is a package that holds secrets. 2 | package secret 3 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testdata/internal/secret/secret.go: -------------------------------------------------------------------------------- 1 | package secret 2 | 3 | // SecretScore is like score but _secret_. 4 | const SecretScore = uint64(43) 5 | 6 | // Original doc 7 | type Burger struct { 8 | Field int 9 | } 10 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testdata/named_import.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | . "fmt" 5 | h "net/http" 6 | ) 7 | 8 | func Example() { 9 | Println(h.CanonicalHeaderKey("accept-encoding")) 10 | } 11 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testdata/parallel.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | "context" 5 | "sync" 6 | ) 7 | 8 | // ParallelizableFunc is a function that can be called concurrently with other instances 9 | // of this function type. 10 | type ParallelizableFunc func(ctx context.Context) error 11 | 12 | // Parallel invokes each of the given parallelizable functions in their own goroutines and 13 | // returns the first error to occur. This method will block until all goroutines have returned. 14 | func Parallel(ctx context.Context, fns ...ParallelizableFunc) error { 15 | var wg sync.WaitGroup 16 | errs := make(chan error, len(fns)) 17 | 18 | for _, fn := range fns { 19 | wg.Add(1) 20 | 21 | go func(fn ParallelizableFunc) { 22 | errs <- fn(ctx) 23 | wg.Done() 24 | }(fn) 25 | } 26 | 27 | wg.Wait() 28 | 29 | for err := range errs { 30 | if err != nil { 31 | return err 32 | } 33 | } 34 | 35 | return nil 36 | } 37 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testdata/typealias.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | "sg/testdata/internal/secret" 5 | ) 6 | 7 | // Type aliased doc 8 | type SecretBurger = secret.Burger 9 | 10 | type BadBurger = struct { 11 | Field string 12 | } 13 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testdata/typeswitch.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | func Switch(interfaceValue interface{}) bool { 4 | switch concreteValue := interfaceValue.(type) { 5 | case int: 6 | return concreteValue*3 > 10 7 | case bool: 8 | return !concreteValue 9 | default: 10 | return false 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testspecial/foo.go: -------------------------------------------------------------------------------- 1 | package testspecial 2 | 3 | func Foo() {} 4 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testspecial/foo_other_test.go: -------------------------------------------------------------------------------- 1 | package testspecial_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "sg/testspecial" 7 | ) 8 | 9 | func TestFoo_Blackbox(*testing.T) { testspecial.Foo() } 10 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testspecial/foo_test.go: -------------------------------------------------------------------------------- 1 | package testspecial 2 | 3 | func TestFoo_Whitebox() { Foo() } 4 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/input/testspecial/go.mod: -------------------------------------------------------------------------------- 1 | module sg/testspecial 2 | 3 | go 1.19 4 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/alias/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | // ^^^^ definition github.com/weightylarva/scip-go . `github.com/weightylarva/scip-go/internal/testdata/snapshots/input/alias`/ 3 | // documentation 4 | // > package main 5 | 6 | // Check that we don't panic 7 | // Copied from https://github.com/golang/go/issues/68877#issuecomment-2290000187 8 | type ( 9 | T struct{} 10 | // ^ definition github.com/weightylarva/scip-go . `github.com/weightylarva/scip-go/internal/testdata/snapshots/input/alias`/T# 11 | // documentation 12 | // > ```go 13 | // > type T struct 14 | // > ``` 15 | // documentation 16 | // > Check that we don't panic 17 | // > Copied from https://github.com/golang/go/issues/68877#issuecomment-2290000187 18 | // documentation 19 | // > ```go 20 | // > struct{} 21 | // > ``` 22 | U = T 23 | // ^ definition github.com/weightylarva/scip-go . `github.com/weightylarva/scip-go/internal/testdata/snapshots/input/alias`/U# 24 | // documentation 25 | // > ```go 26 | // > type U = T 27 | // > ``` 28 | // documentation 29 | // > Check that we don't panic 30 | // > Copied from https://github.com/golang/go/issues/68877#issuecomment-2290000187 31 | // documentation 32 | // > ```go 33 | // > struct{} 34 | // > ``` 35 | // ^ reference github.com/weightylarva/scip-go . `github.com/weightylarva/scip-go/internal/testdata/snapshots/input/alias`/T# 36 | V = U 37 | // ^ definition github.com/weightylarva/scip-go . `github.com/weightylarva/scip-go/internal/testdata/snapshots/input/alias`/V# 38 | // documentation 39 | // > ```go 40 | // > type V = U 41 | // > ``` 42 | // documentation 43 | // > Check that we don't panic 44 | // > Copied from https://github.com/golang/go/issues/68877#issuecomment-2290000187 45 | // documentation 46 | // > ```go 47 | // > struct{} 48 | // > ``` 49 | // ^ reference github.com/weightylarva/scip-go . `github.com/weightylarva/scip-go/internal/testdata/snapshots/input/alias`/U# 50 | S U 51 | // ^ definition github.com/weightylarva/scip-go . `github.com/weightylarva/scip-go/internal/testdata/snapshots/input/alias`/S# 52 | // documentation 53 | // > ```go 54 | // > type S struct 55 | // > ``` 56 | // documentation 57 | // > Check that we don't panic 58 | // > Copied from https://github.com/golang/go/issues/68877#issuecomment-2290000187 59 | // documentation 60 | // > ```go 61 | // > struct{} 62 | // > ``` 63 | // ^ reference github.com/weightylarva/scip-go . `github.com/weightylarva/scip-go/internal/testdata/snapshots/input/alias`/U# 64 | Z int32 65 | // ^ definition github.com/weightylarva/scip-go . `github.com/weightylarva/scip-go/internal/testdata/snapshots/input/alias`/Z# 66 | // documentation 67 | // > Check that we don't panic 68 | // > Copied from https://github.com/golang/go/issues/68877#issuecomment-2290000187 69 | // documentation 70 | // > ```go 71 | // > int32 72 | // > ``` 73 | ) 74 | 75 | func f(u U) {} 76 | // ^ definition github.com/weightylarva/scip-go . `github.com/weightylarva/scip-go/internal/testdata/snapshots/input/alias`/f(). 77 | // documentation 78 | // > ```go 79 | // > func f(u U) 80 | // > ``` 81 | // ^ definition local 0 82 | // ^ reference github.com/weightylarva/scip-go . `github.com/weightylarva/scip-go/internal/testdata/snapshots/input/alias`/U# 83 | 84 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/embedded/embedded.go: -------------------------------------------------------------------------------- 1 | package embedded 2 | // ^^^^^^^^ reference 0.1.test `sg/embedded`/ 3 | 4 | import ( 5 | "fmt" 6 | // ^^^ reference github.com/golang/go/src go1.22 fmt/ 7 | "os/exec" 8 | // ^^^^^^^ reference github.com/golang/go/src go1.22 `os/exec`/ 9 | ) 10 | 11 | type osExecCommand struct { 12 | // ^^^^^^^^^^^^^ definition 0.1.test `sg/embedded`/osExecCommand# 13 | // documentation 14 | // > ```go 15 | // > type osExecCommand struct 16 | // > ``` 17 | // documentation 18 | // > ```go 19 | // > struct { 20 | // > *Cmd 21 | // > } 22 | // > ``` 23 | // relationship github.com/golang/go/src go1.22 context/stringer# implementation 24 | // relationship github.com/golang/go/src go1.22 fmt/Stringer# implementation 25 | // relationship github.com/golang/go/src go1.22 runtime/stringer# implementation 26 | *exec.Cmd 27 | // ^^^^ reference github.com/golang/go/src go1.22 `os/exec`/ 28 | // ^^^ definition 0.1.test `sg/embedded`/osExecCommand#Cmd. 29 | // documentation 30 | // > ```go 31 | // > struct field Cmd *os/exec.Cmd 32 | // > ``` 33 | // ^^^ reference github.com/golang/go/src go1.22 `os/exec`/Cmd# 34 | } 35 | 36 | func wrapExecCommand(c *exec.Cmd) { 37 | // ^^^^^^^^^^^^^^^ definition 0.1.test `sg/embedded`/wrapExecCommand(). 38 | // documentation 39 | // > ```go 40 | // > func wrapExecCommand(c *Cmd) 41 | // > ``` 42 | // ^ definition local 0 43 | // ^^^^ reference github.com/golang/go/src go1.22 `os/exec`/ 44 | // ^^^ reference github.com/golang/go/src go1.22 `os/exec`/Cmd# 45 | _ = &osExecCommand{Cmd: c} 46 | // ^^^^^^^^^^^^^ reference 0.1.test `sg/embedded`/osExecCommand# 47 | // ^^^ reference 0.1.test `sg/embedded`/osExecCommand#Cmd. 48 | // ^ reference local 0 49 | } 50 | 51 | type Inner struct { 52 | // ^^^^^ definition 0.1.test `sg/embedded`/Inner# 53 | // documentation 54 | // > ```go 55 | // > type Inner struct 56 | // > ``` 57 | // documentation 58 | // > ```go 59 | // > struct { 60 | // > X int 61 | // > Y int 62 | // > Z int 63 | // > } 64 | // > ``` 65 | X int 66 | // ^ definition 0.1.test `sg/embedded`/Inner#X. 67 | // documentation 68 | // > ```go 69 | // > struct field X int 70 | // > ``` 71 | Y int 72 | // ^ definition 0.1.test `sg/embedded`/Inner#Y. 73 | // documentation 74 | // > ```go 75 | // > struct field Y int 76 | // > ``` 77 | Z int 78 | // ^ definition 0.1.test `sg/embedded`/Inner#Z. 79 | // documentation 80 | // > ```go 81 | // > struct field Z int 82 | // > ``` 83 | } 84 | 85 | type Outer struct { 86 | // ^^^^^ definition 0.1.test `sg/embedded`/Outer# 87 | // documentation 88 | // > ```go 89 | // > type Outer struct 90 | // > ``` 91 | // documentation 92 | // > ```go 93 | // > struct { 94 | // > Inner 95 | // > W int 96 | // > } 97 | // > ``` 98 | Inner 99 | // ^^^^^ definition 0.1.test `sg/embedded`/Outer#Inner. 100 | // documentation 101 | // > ```go 102 | // > struct field Inner sg/embedded.Inner 103 | // > ``` 104 | // ^^^^^ reference 0.1.test `sg/embedded`/Inner# 105 | W int 106 | // ^ definition 0.1.test `sg/embedded`/Outer#W. 107 | // documentation 108 | // > ```go 109 | // > struct field W int 110 | // > ``` 111 | } 112 | 113 | func useOfCompositeStructs() { 114 | // ^^^^^^^^^^^^^^^^^^^^^ definition 0.1.test `sg/embedded`/useOfCompositeStructs(). 115 | // documentation 116 | // > ```go 117 | // > func useOfCompositeStructs() 118 | // > ``` 119 | o := Outer{ 120 | // ^ definition local 1 121 | // ^^^^^ reference 0.1.test `sg/embedded`/Outer# 122 | Inner: Inner{ 123 | // ^^^^^ reference 0.1.test `sg/embedded`/Outer#Inner. 124 | // ^^^^^ reference 0.1.test `sg/embedded`/Inner# 125 | X: 1, 126 | // ^ reference 0.1.test `sg/embedded`/Inner#X. 127 | Y: 2, 128 | // ^ reference 0.1.test `sg/embedded`/Inner#Y. 129 | Z: 3, 130 | // ^ reference 0.1.test `sg/embedded`/Inner#Z. 131 | }, 132 | W: 4, 133 | // ^ reference 0.1.test `sg/embedded`/Outer#W. 134 | } 135 | 136 | fmt.Printf("> %d\n", o.X) 137 | // ^^^ reference github.com/golang/go/src go1.22 fmt/ 138 | // ^^^^^^ reference github.com/golang/go/src go1.22 fmt/Printf(). 139 | // ^ reference local 1 140 | // ^ reference 0.1.test `sg/embedded`/Inner#X. 141 | fmt.Println(o.Inner.Y) 142 | // ^^^ reference github.com/golang/go/src go1.22 fmt/ 143 | // ^^^^^^^ reference github.com/golang/go/src go1.22 fmt/Println(). 144 | // ^ reference local 1 145 | // ^^^^^ reference 0.1.test `sg/embedded`/Outer#Inner. 146 | // ^ reference 0.1.test `sg/embedded`/Inner#Y. 147 | } 148 | 149 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/embedded/internal/nested.go: -------------------------------------------------------------------------------- 1 | package nested_internal 2 | // ^^^^^^^^^^^^^^^ definition 0.1.test `sg/embedded/internal`/ 3 | // documentation 4 | // > package nested_internal 5 | 6 | import ( 7 | "fmt" 8 | // ^^^ reference github.com/golang/go/src go1.22 fmt/ 9 | "sg/embedded" 10 | // ^^^^^^^^^^^ reference 0.1.test `sg/embedded`/ 11 | ) 12 | 13 | func Something(recent embedded.RecentCommittersResults) { 14 | // ^^^^^^^^^ definition 0.1.test `sg/embedded/internal`/Something(). 15 | // documentation 16 | // > ```go 17 | // > func Something(recent RecentCommittersResults) 18 | // > ``` 19 | // ^^^^^^ definition local 0 20 | // ^^^^^^^^ reference 0.1.test `sg/embedded`/ 21 | // ^^^^^^^^^^^^^^^^^^^^^^^ reference 0.1.test `sg/embedded`/RecentCommittersResults# 22 | for _, commit := range recent.Nodes { 23 | // ^^^^^^ definition local 1 24 | // ^^^^^^ reference local 0 25 | // ^^^^^ reference 0.1.test `sg/embedded`/RecentCommittersResults#Nodes. 26 | for _, author := range commit.Authors.Nodes { 27 | // ^^^^^^ definition local 2 28 | // ^^^^^^ reference local 1 29 | // ^^^^^^^ reference 0.1.test `sg/embedded`/RecentCommittersResults#Nodes.Authors. 30 | // ^^^^^ reference 0.1.test `sg/embedded`/RecentCommittersResults#Nodes.Authors.Nodes. 31 | fmt.Println(author.Name) 32 | // ^^^ reference github.com/golang/go/src go1.22 fmt/ 33 | // ^^^^^^^ reference github.com/golang/go/src go1.22 fmt/Println(). 34 | // ^^^^^^ reference local 2 35 | // ^^^^ reference 0.1.test `sg/embedded`/RecentCommittersResults#Nodes.Authors.Nodes.Name. 36 | } 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/embedded/nested.go: -------------------------------------------------------------------------------- 1 | package embedded 2 | // ^^^^^^^^ definition 0.1.test `sg/embedded`/ 3 | // documentation 4 | // > package embedded 5 | 6 | import "net/http" 7 | // ^^^^^^^^ reference github.com/golang/go/src go1.22 `net/http`/ 8 | 9 | type NestedHandler struct { 10 | // ^^^^^^^^^^^^^ definition 0.1.test `sg/embedded`/NestedHandler# 11 | // documentation 12 | // > ```go 13 | // > type NestedHandler struct 14 | // > ``` 15 | // documentation 16 | // > ```go 17 | // > struct { 18 | // > Handler 19 | // > Other int 20 | // > } 21 | // > ``` 22 | // relationship github.com/golang/go/src go1.22 `net/http`/Handler# implementation 23 | http.Handler 24 | // ^^^^ reference github.com/golang/go/src go1.22 `net/http`/ 25 | // ^^^^^^^ definition 0.1.test `sg/embedded`/NestedHandler#Handler. 26 | // documentation 27 | // > ```go 28 | // > struct field Handler net/http.Handler 29 | // > ``` 30 | // ^^^^^^^ reference github.com/golang/go/src go1.22 `net/http`/Handler# 31 | 32 | // Wow, a great thing for integers 33 | Other int 34 | // ^^^^^ definition 0.1.test `sg/embedded`/NestedHandler#Other. 35 | // documentation 36 | // > ```go 37 | // > struct field Other int 38 | // > ``` 39 | } 40 | 41 | func NestedExample(n NestedHandler) { 42 | // ^^^^^^^^^^^^^ definition 0.1.test `sg/embedded`/NestedExample(). 43 | // documentation 44 | // > ```go 45 | // > func NestedExample(n NestedHandler) 46 | // > ``` 47 | // ^ definition local 0 48 | // ^^^^^^^^^^^^^ reference 0.1.test `sg/embedded`/NestedHandler# 49 | _ = n.Handler.ServeHTTP 50 | // ^ reference local 0 51 | // ^^^^^^^ reference 0.1.test `sg/embedded`/NestedHandler#Handler. 52 | // ^^^^^^^^^ reference github.com/golang/go/src go1.22 `net/http`/Handler#ServeHTTP. 53 | _ = n.ServeHTTP 54 | // ^ reference local 0 55 | // ^^^^^^^^^ reference github.com/golang/go/src go1.22 `net/http`/Handler#ServeHTTP. 56 | _ = n.Other 57 | // ^ reference local 0 58 | // ^^^^^ reference 0.1.test `sg/embedded`/NestedHandler#Other. 59 | } 60 | 61 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/embedded/something.go: -------------------------------------------------------------------------------- 1 | package embedded 2 | // ^^^^^^^^ reference 0.1.test `sg/embedded`/ 3 | 4 | import "fmt" 5 | // ^^^ reference github.com/golang/go/src go1.22 fmt/ 6 | 7 | type RecentCommittersResults struct { 8 | // ^^^^^^^^^^^^^^^^^^^^^^^ definition 0.1.test `sg/embedded`/RecentCommittersResults# 9 | // documentation 10 | // > ```go 11 | // > type RecentCommittersResults struct 12 | // > ``` 13 | // documentation 14 | // > ```go 15 | // > struct { 16 | // > Nodes []struct { 17 | // > Authors struct { 18 | // > Nodes []struct { 19 | // > Date string 20 | // > Email string 21 | // > Name string 22 | // > User struct { 23 | // > Login string 24 | // > } 25 | // > AvatarURL string 26 | // > } 27 | // > } 28 | // > } 29 | // > PageInfo struct { 30 | // > HasNextPage bool 31 | // > } 32 | // > } 33 | // > ``` 34 | Nodes []struct { 35 | // ^^^^^ definition 0.1.test `sg/embedded`/RecentCommittersResults#Nodes. 36 | // documentation 37 | // > ```go 38 | // > struct field Nodes []struct{Authors struct{Nodes []struct{Date string; Email string; Name string; User struct{Login string}; AvatarURL string}}} 39 | // > ``` 40 | Authors struct { 41 | // ^^^^^^^ definition 0.1.test `sg/embedded`/RecentCommittersResults#Nodes.Authors. 42 | // documentation 43 | // > ```go 44 | // > struct field Authors struct{Nodes []struct{Date string; Email string; Name string; User struct{Login string}; AvatarURL string}} 45 | // > ``` 46 | Nodes []struct { 47 | // ^^^^^ definition 0.1.test `sg/embedded`/RecentCommittersResults#Nodes.Authors.Nodes. 48 | // documentation 49 | // > ```go 50 | // > struct field Nodes []struct{Date string; Email string; Name string; User struct{Login string}; AvatarURL string} 51 | // > ``` 52 | Date string 53 | // ^^^^ definition 0.1.test `sg/embedded`/RecentCommittersResults#Nodes.Authors.Nodes.Date. 54 | // documentation 55 | // > ```go 56 | // > struct field Date string 57 | // > ``` 58 | Email string 59 | // ^^^^^ definition 0.1.test `sg/embedded`/RecentCommittersResults#Nodes.Authors.Nodes.Email. 60 | // documentation 61 | // > ```go 62 | // > struct field Email string 63 | // > ``` 64 | Name string 65 | // ^^^^ definition 0.1.test `sg/embedded`/RecentCommittersResults#Nodes.Authors.Nodes.Name. 66 | // documentation 67 | // > ```go 68 | // > struct field Name string 69 | // > ``` 70 | User struct { 71 | // ^^^^ definition 0.1.test `sg/embedded`/RecentCommittersResults#Nodes.Authors.Nodes.User. 72 | // documentation 73 | // > ```go 74 | // > struct field User struct{Login string} 75 | // > ``` 76 | Login string 77 | // ^^^^^ definition 0.1.test `sg/embedded`/RecentCommittersResults#Nodes.Authors.Nodes.User.Login. 78 | // documentation 79 | // > ```go 80 | // > struct field Login string 81 | // > ``` 82 | } 83 | AvatarURL string 84 | // ^^^^^^^^^ definition 0.1.test `sg/embedded`/RecentCommittersResults#Nodes.Authors.Nodes.AvatarURL. 85 | // documentation 86 | // > ```go 87 | // > struct field AvatarURL string 88 | // > ``` 89 | } 90 | } 91 | } 92 | PageInfo struct { 93 | // ^^^^^^^^ definition 0.1.test `sg/embedded`/RecentCommittersResults#PageInfo. 94 | // documentation 95 | // > ```go 96 | // > struct field PageInfo struct{HasNextPage bool} 97 | // > ``` 98 | HasNextPage bool 99 | // ^^^^^^^^^^^ definition 0.1.test `sg/embedded`/RecentCommittersResults#PageInfo.HasNextPage. 100 | // documentation 101 | // > ```go 102 | // > struct field HasNextPage bool 103 | // > ``` 104 | } 105 | } 106 | 107 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/generallyeric/generallyeric.go: -------------------------------------------------------------------------------- 1 | // generallyeric -> generic for short 2 | package generallyeric 3 | // ^^^^^^^^^^^^^ definition 0.1.test `sg/generallyeric`/ 4 | // documentation 5 | // > generallyeric -> generic for short 6 | 7 | import "fmt" 8 | // ^^^ reference github.com/golang/go/src go1.22 fmt/ 9 | 10 | func Print[T any](s []T) { 11 | // ^^^^^ definition 0.1.test `sg/generallyeric`/Print(). 12 | // documentation 13 | // > ```go 14 | // > func Print[T any](s []T) 15 | // > ``` 16 | // ^ definition local 0 17 | // ^ definition local 1 18 | // ^ reference local 0 19 | for _, v := range s { 20 | // ^ definition local 2 21 | // ^ reference local 1 22 | fmt.Print(v) 23 | // ^^^ reference github.com/golang/go/src go1.22 fmt/ 24 | // ^^^^^ reference github.com/golang/go/src go1.22 fmt/Print(). 25 | // ^ reference local 2 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/generallyeric/new_operators.go: -------------------------------------------------------------------------------- 1 | package generallyeric 2 | // ^^^^^^^^^^^^^ reference 0.1.test `sg/generallyeric`/ 3 | 4 | import "golang.org/x/exp/constraints" 5 | // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference golang.org/x/exp 47842c84f3db `golang.org/x/exp/constraints`/ 6 | 7 | type Number interface { 8 | // ^^^^^^ definition 0.1.test `sg/generallyeric`/Number# 9 | // documentation 10 | // > ```go 11 | // > type Number interface 12 | // > ``` 13 | // documentation 14 | // > ```go 15 | // > interface { 16 | // > Float | Integer | Complex 17 | // > } 18 | // > ``` 19 | constraints.Float | constraints.Integer | constraints.Complex 20 | // ^^^^^^^^^^^ reference golang.org/x/exp 47842c84f3db `golang.org/x/exp/constraints`/ 21 | // ^^^^^ reference golang.org/x/exp 47842c84f3db `golang.org/x/exp/constraints`/Float# 22 | // ^^^^^^^^^^^ reference golang.org/x/exp 47842c84f3db `golang.org/x/exp/constraints`/ 23 | // ^^^^^^^ reference golang.org/x/exp 47842c84f3db `golang.org/x/exp/constraints`/Integer# 24 | // ^^^^^^^^^^^ reference golang.org/x/exp 47842c84f3db `golang.org/x/exp/constraints`/ 25 | // ^^^^^^^ reference golang.org/x/exp 47842c84f3db `golang.org/x/exp/constraints`/Complex# 26 | } 27 | 28 | func Double[T Number](value T) T { 29 | // ^^^^^^ definition 0.1.test `sg/generallyeric`/Double(). 30 | // documentation 31 | // > ```go 32 | // > func Double[T Number](value T) T 33 | // > ``` 34 | // ^ definition local 0 35 | // ^^^^^^ reference 0.1.test `sg/generallyeric`/Number# 36 | // ^^^^^ definition local 1 37 | // ^ reference local 0 38 | // ^ reference local 0 39 | return value * 2 40 | // ^^^^^ reference local 1 41 | } 42 | 43 | type Box[T any] struct { 44 | // ^^^ definition 0.1.test `sg/generallyeric`/Box# 45 | // documentation 46 | // > ```go 47 | // > type Box struct 48 | // > ``` 49 | // documentation 50 | // > ```go 51 | // > struct { 52 | // > Something T 53 | // > } 54 | // > ``` 55 | // ^ definition local 2 56 | Something T 57 | // ^^^^^^^^^ definition 0.1.test `sg/generallyeric`/Box#Something. 58 | // documentation 59 | // > ```go 60 | // > struct field Something T 61 | // > ``` 62 | // ^ reference local 2 63 | } 64 | 65 | type handler[T any] struct { 66 | // ^^^^^^^ definition 0.1.test `sg/generallyeric`/handler# 67 | // documentation 68 | // > ```go 69 | // > type handler struct 70 | // > ``` 71 | // documentation 72 | // > ```go 73 | // > struct { 74 | // > Box[T] 75 | // > Another string 76 | // > } 77 | // > ``` 78 | // ^ definition local 3 79 | Box[T] 80 | // ^^^ definition 0.1.test `sg/generallyeric`/handler#Box. 81 | // documentation 82 | // > ```go 83 | // > struct field Box sg/generallyeric.Box[T] 84 | // > ``` 85 | // ^^^ reference 0.1.test `sg/generallyeric`/Box# 86 | // ^ reference local 3 87 | Another string 88 | // ^^^^^^^ definition 0.1.test `sg/generallyeric`/handler#Another. 89 | // documentation 90 | // > ```go 91 | // > struct field Another string 92 | // > ``` 93 | } 94 | 95 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/generallyeric/person.go: -------------------------------------------------------------------------------- 1 | package generallyeric 2 | // ^^^^^^^^^^^^^ reference 0.1.test `sg/generallyeric`/ 3 | 4 | import "fmt" 5 | // ^^^ reference github.com/golang/go/src go1.22 fmt/ 6 | 7 | type Person interface { 8 | // ^^^^^^ definition 0.1.test `sg/generallyeric`/Person# 9 | // documentation 10 | // > ```go 11 | // > type Person interface 12 | // > ``` 13 | // documentation 14 | // > ```go 15 | // > interface { 16 | // > Work() 17 | // > } 18 | // > ``` 19 | Work() 20 | // ^^^^ definition 0.1.test `sg/generallyeric`/Person#Work. 21 | // documentation 22 | // > ```go 23 | // > func (Person).Work() 24 | // > ``` 25 | } 26 | 27 | type worker string 28 | // ^^^^^^ definition 0.1.test `sg/generallyeric`/worker# 29 | // documentation 30 | // > ```go 31 | // > string 32 | // > ``` 33 | // relationship 0.1.test `sg/generallyeric`/Person# implementation 34 | 35 | func (w worker) Work() { 36 | // ^ definition local 0 37 | // ^^^^^^ reference 0.1.test `sg/generallyeric`/worker# 38 | // ^^^^ definition 0.1.test `sg/generallyeric`/worker#Work(). 39 | // documentation 40 | // > ```go 41 | // > func (worker).Work() 42 | // > ``` 43 | // relationship 0.1.test `sg/generallyeric`/Person#Work. implementation 44 | fmt.Printf("%s is working\n", w) 45 | // ^^^ reference github.com/golang/go/src go1.22 fmt/ 46 | // ^^^^^^ reference github.com/golang/go/src go1.22 fmt/Printf(). 47 | // ^ reference local 0 48 | } 49 | 50 | func DoWork[T Person](things []T) { 51 | // ^^^^^^ definition 0.1.test `sg/generallyeric`/DoWork(). 52 | // documentation 53 | // > ```go 54 | // > func DoWork[T Person](things []T) 55 | // > ``` 56 | // ^ definition local 1 57 | // ^^^^^^ reference 0.1.test `sg/generallyeric`/Person# 58 | // ^^^^^^ definition local 2 59 | // ^ reference local 1 60 | for _, v := range things { 61 | // ^ definition local 3 62 | // ^^^^^^ reference local 2 63 | v.Work() 64 | // ^ reference local 3 65 | // ^^^^ reference 0.1.test `sg/generallyeric`/Person#Work. 66 | } 67 | } 68 | 69 | func main() { 70 | // ^^^^ definition 0.1.test `sg/generallyeric`/main(). 71 | // documentation 72 | // > ```go 73 | // > func main() 74 | // > ``` 75 | var a, b, c worker 76 | // ^ definition local 4 77 | // ^ definition local 5 78 | // ^ definition local 6 79 | // ^^^^^^ reference 0.1.test `sg/generallyeric`/worker# 80 | a = "A" 81 | // ^ reference local 4 82 | b = "B" 83 | // ^ reference local 5 84 | c = "C" 85 | // ^ reference local 6 86 | DoWork([]worker{a, b, c}) 87 | // ^^^^^^ reference 0.1.test `sg/generallyeric`/DoWork(). 88 | // ^^^^^^ reference 0.1.test `sg/generallyeric`/worker# 89 | // ^ reference local 4 90 | // ^ reference local 5 91 | // ^ reference local 6 92 | } 93 | 94 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/impls/impls.go: -------------------------------------------------------------------------------- 1 | package impls 2 | // ^^^^^ definition 0.1.test `sg/impls`/ 3 | // documentation 4 | // > package impls 5 | 6 | type I1 interface { 7 | // ^^ definition 0.1.test `sg/impls`/I1# 8 | // documentation 9 | // > ```go 10 | // > type I1 interface 11 | // > ``` 12 | // documentation 13 | // > ```go 14 | // > interface { 15 | // > F1() 16 | // > } 17 | // > ``` 18 | F1() 19 | // ^^ definition 0.1.test `sg/impls`/I1#F1. 20 | // documentation 21 | // > ```go 22 | // > func (I1).F1() 23 | // > ``` 24 | } 25 | 26 | type I1Clone interface { 27 | // ^^^^^^^ definition 0.1.test `sg/impls`/I1Clone# 28 | // documentation 29 | // > ```go 30 | // > type I1Clone interface 31 | // > ``` 32 | // documentation 33 | // > ```go 34 | // > interface { 35 | // > F1() 36 | // > } 37 | // > ``` 38 | F1() 39 | // ^^ definition 0.1.test `sg/impls`/I1Clone#F1. 40 | // documentation 41 | // > ```go 42 | // > func (I1Clone).F1() 43 | // > ``` 44 | } 45 | 46 | type IfaceOther interface { 47 | // ^^^^^^^^^^ definition 0.1.test `sg/impls`/IfaceOther# 48 | // documentation 49 | // > ```go 50 | // > type IfaceOther interface 51 | // > ``` 52 | // documentation 53 | // > ```go 54 | // > interface { 55 | // > Another() 56 | // > Something() 57 | // > } 58 | // > ``` 59 | Something() 60 | // ^^^^^^^^^ definition 0.1.test `sg/impls`/IfaceOther#Something. 61 | // documentation 62 | // > ```go 63 | // > func (IfaceOther).Something() 64 | // > ``` 65 | Another() 66 | // ^^^^^^^ definition 0.1.test `sg/impls`/IfaceOther#Another. 67 | // documentation 68 | // > ```go 69 | // > func (IfaceOther).Another() 70 | // > ``` 71 | } 72 | 73 | type T1 int 74 | // ^^ definition 0.1.test `sg/impls`/T1# 75 | // documentation 76 | // > ```go 77 | // > int 78 | // > ``` 79 | // relationship 0.1.test `sg/impls`/I1# implementation 80 | // relationship 0.1.test `sg/impls`/I1Clone# implementation 81 | 82 | func (r T1) F1() {} 83 | // ^ definition local 0 84 | // ^^ reference 0.1.test `sg/impls`/T1# 85 | // ^^ definition 0.1.test `sg/impls`/T1#F1(). 86 | // documentation 87 | // > ```go 88 | // > func (T1).F1() 89 | // > ``` 90 | // relationship 0.1.test `sg/impls`/I1#F1. implementation 91 | // relationship 0.1.test `sg/impls`/I1Clone#F1. implementation 92 | 93 | type T2 int 94 | // ^^ definition 0.1.test `sg/impls`/T2# 95 | // documentation 96 | // > ```go 97 | // > int 98 | // > ``` 99 | // relationship 0.1.test `sg/impls`/I1# implementation 100 | // relationship 0.1.test `sg/impls`/I1Clone# implementation 101 | 102 | func (r T2) F1() {} 103 | // ^ definition local 1 104 | // ^^ reference 0.1.test `sg/impls`/T2# 105 | // ^^ definition 0.1.test `sg/impls`/T2#F1(). 106 | // documentation 107 | // > ```go 108 | // > func (T2).F1() 109 | // > ``` 110 | // relationship 0.1.test `sg/impls`/I1#F1. implementation 111 | // relationship 0.1.test `sg/impls`/I1Clone#F1. implementation 112 | func (r T2) F2() {} 113 | // ^ definition local 2 114 | // ^^ reference 0.1.test `sg/impls`/T2# 115 | // ^^ definition 0.1.test `sg/impls`/T2#F2(). 116 | // documentation 117 | // > ```go 118 | // > func (T2).F2() 119 | // > ``` 120 | 121 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/impls/remote_impls.go: -------------------------------------------------------------------------------- 1 | package impls 2 | // ^^^^^ reference 0.1.test `sg/impls`/ 3 | 4 | import "net/http" 5 | // ^^^^^^^^ reference github.com/golang/go/src go1.22 `net/http`/ 6 | 7 | func Something(r http.ResponseWriter) {} 8 | // ^^^^^^^^^ definition 0.1.test `sg/impls`/Something(). 9 | // documentation 10 | // > ```go 11 | // > func Something(r ResponseWriter) 12 | // > ``` 13 | // ^ definition local 0 14 | // ^^^^ reference github.com/golang/go/src go1.22 `net/http`/ 15 | // ^^^^^^^^^^^^^^ reference github.com/golang/go/src go1.22 `net/http`/ResponseWriter# 16 | 17 | type MyWriter struct{} 18 | // ^^^^^^^^ definition 0.1.test `sg/impls`/MyWriter# 19 | // documentation 20 | // > ```go 21 | // > type MyWriter struct 22 | // > ``` 23 | // documentation 24 | // > ```go 25 | // > struct{} 26 | // > ``` 27 | // relationship github.com/golang/go/src go1.22 `crypto/tls`/transcriptHash# implementation 28 | // relationship github.com/golang/go/src go1.22 `internal/bisect`/Writer# implementation 29 | // relationship github.com/golang/go/src go1.22 `net/http`/ResponseWriter# implementation 30 | // relationship github.com/golang/go/src go1.22 io/Writer# implementation 31 | 32 | func (w MyWriter) Header() http.Header { panic("") } 33 | // ^ definition local 1 34 | // ^^^^^^^^ reference 0.1.test `sg/impls`/MyWriter# 35 | // ^^^^^^ definition 0.1.test `sg/impls`/MyWriter#Header(). 36 | // documentation 37 | // > ```go 38 | // > func (MyWriter).Header() Header 39 | // > ``` 40 | // relationship github.com/golang/go/src go1.22 `net/http`/ResponseWriter#Header. implementation 41 | // ^^^^ reference github.com/golang/go/src go1.22 `net/http`/ 42 | // ^^^^^^ reference github.com/golang/go/src go1.22 `net/http`/Header# 43 | func (w MyWriter) Write([]byte) (int, error) { panic("") } 44 | // ^ definition local 2 45 | // ^^^^^^^^ reference 0.1.test `sg/impls`/MyWriter# 46 | // ^^^^^ definition 0.1.test `sg/impls`/MyWriter#Write(). 47 | // documentation 48 | // > ```go 49 | // > func (MyWriter).Write([]byte) (int, error) 50 | // > ``` 51 | // relationship github.com/golang/go/src go1.22 `crypto/tls`/transcriptHash#Write. implementation 52 | // relationship github.com/golang/go/src go1.22 `internal/bisect`/Writer#Write. implementation 53 | // relationship github.com/golang/go/src go1.22 `net/http`/ResponseWriter#Write. implementation 54 | // relationship github.com/golang/go/src go1.22 io/Writer#Write. implementation 55 | func (w MyWriter) WriteHeader(statusCode int) { panic("") } 56 | // ^ definition local 3 57 | // ^^^^^^^^ reference 0.1.test `sg/impls`/MyWriter# 58 | // ^^^^^^^^^^^ definition 0.1.test `sg/impls`/MyWriter#WriteHeader(). 59 | // documentation 60 | // > ```go 61 | // > func (MyWriter).WriteHeader(statusCode int) 62 | // > ``` 63 | // relationship github.com/golang/go/src go1.22 `net/http`/ResponseWriter#WriteHeader. implementation 64 | // ^^^^^^^^^^ definition local 4 65 | 66 | func Another() { 67 | // ^^^^^^^ definition 0.1.test `sg/impls`/Another(). 68 | // documentation 69 | // > ```go 70 | // > func Another() 71 | // > ``` 72 | Something(MyWriter{}) 73 | // ^^^^^^^^^ reference 0.1.test `sg/impls`/Something(). 74 | // ^^^^^^^^ reference 0.1.test `sg/impls`/MyWriter# 75 | } 76 | 77 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/initial/builtin_types.go: -------------------------------------------------------------------------------- 1 | package initial 2 | // ^^^^^^^ reference 0.1.test `sg/initial`/ 3 | 4 | func UsesBuiltin() int { 5 | // ^^^^^^^^^^^ definition 0.1.test `sg/initial`/UsesBuiltin(). 6 | // documentation 7 | // > ```go 8 | // > func UsesBuiltin() int 9 | // > ``` 10 | var x int = 5 11 | // ^ definition local 0 12 | return x 13 | // ^ reference local 0 14 | } 15 | 16 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/initial/func_declarations.go: -------------------------------------------------------------------------------- 1 | package initial 2 | // ^^^^^^^ reference 0.1.test `sg/initial`/ 3 | 4 | func UsesLater() { 5 | // ^^^^^^^^^ definition 0.1.test `sg/initial`/UsesLater(). 6 | // documentation 7 | // > ```go 8 | // > func UsesLater() 9 | // > ``` 10 | DefinedLater() 11 | // ^^^^^^^^^^^^ reference 0.1.test `sg/initial`/DefinedLater(). 12 | } 13 | 14 | func DefinedLater() {} 15 | // ^^^^^^^^^^^^ definition 0.1.test `sg/initial`/DefinedLater(). 16 | // documentation 17 | // > ```go 18 | // > func DefinedLater() 19 | // > ``` 20 | 21 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/initial/methods_and_receivers.go: -------------------------------------------------------------------------------- 1 | package initial 2 | // ^^^^^^^ reference 0.1.test `sg/initial`/ 3 | 4 | import "fmt" 5 | // ^^^ reference github.com/golang/go/src go1.22 fmt/ 6 | 7 | type MyStruct struct{ f, y int } 8 | // ^^^^^^^^ definition 0.1.test `sg/initial`/MyStruct# 9 | // documentation 10 | // > ```go 11 | // > type MyStruct struct 12 | // > ``` 13 | // documentation 14 | // > ```go 15 | // > struct { 16 | // > f int 17 | // > y int 18 | // > } 19 | // > ``` 20 | // ^ definition 0.1.test `sg/initial`/MyStruct#f. 21 | // documentation 22 | // > ```go 23 | // > struct field f int 24 | // > ``` 25 | // ^ definition 0.1.test `sg/initial`/MyStruct#y. 26 | // documentation 27 | // > ```go 28 | // > struct field y int 29 | // > ``` 30 | 31 | func (m MyStruct) RecvFunction(b int) int { return m.f + b } 32 | // ^ definition local 0 33 | // ^^^^^^^^ reference 0.1.test `sg/initial`/MyStruct# 34 | // ^^^^^^^^^^^^ definition 0.1.test `sg/initial`/MyStruct#RecvFunction(). 35 | // documentation 36 | // > ```go 37 | // > func (MyStruct).RecvFunction(b int) int 38 | // > ``` 39 | // ^ definition local 1 40 | // ^ reference local 0 41 | // ^ reference 0.1.test `sg/initial`/MyStruct#f. 42 | // ^ reference local 1 43 | 44 | func SomethingElse() { 45 | // ^^^^^^^^^^^^^ definition 0.1.test `sg/initial`/SomethingElse(). 46 | // documentation 47 | // > ```go 48 | // > func SomethingElse() 49 | // > ``` 50 | s := MyStruct{f: 0} 51 | // ^ definition local 2 52 | // ^^^^^^^^ reference 0.1.test `sg/initial`/MyStruct# 53 | // ^ reference 0.1.test `sg/initial`/MyStruct#f. 54 | fmt.Println(s) 55 | // ^^^ reference github.com/golang/go/src go1.22 fmt/ 56 | // ^^^^^^^ reference github.com/golang/go/src go1.22 fmt/Println(). 57 | // ^ reference local 2 58 | } 59 | 60 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/initial/package_definition.go: -------------------------------------------------------------------------------- 1 | // This is a module for testing purposes. 2 | // This should now be the place that has a definition 3 | package initial 4 | // ^^^^^^^ definition 0.1.test `sg/initial`/ 5 | // documentation 6 | // > This is a module for testing purposes. 7 | // > This should now be the place that has a definition 8 | 9 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/initial/rangefunc.go: -------------------------------------------------------------------------------- 1 | package initial 2 | // ^^^^^^^ reference 0.1.test `sg/initial`/ 3 | 4 | import ( 5 | "slices" 6 | // ^^^^^^ reference github.com/golang/go/src go1.22 slices/ 7 | ) 8 | 9 | func f(xs []int) int { 10 | // ^ definition 0.1.test `sg/initial`/f(). 11 | // documentation 12 | // > ```go 13 | // > func f(xs []int) int 14 | // > ``` 15 | // ^^ definition local 0 16 | for _, x := range slices.All(xs) { 17 | // ^ definition local 1 18 | // ^^^^^^ reference github.com/golang/go/src go1.22 slices/ 19 | // ^^^ reference github.com/golang/go/src go1.22 slices/All(). 20 | // ^^ reference local 0 21 | return x 22 | // ^ reference local 1 23 | } 24 | return -1 25 | } 26 | 27 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/initial/toplevel_decls.go: -------------------------------------------------------------------------------- 1 | package initial 2 | // ^^^^^^^ reference 0.1.test `sg/initial`/ 3 | 4 | const MY_THING = 10 5 | // ^^^^^^^^ definition 0.1.test `sg/initial`/MY_THING. 6 | // documentation 7 | // > ```go 8 | // > const MY_THING untyped int = 10 9 | // > ``` 10 | const OTHER_THING = MY_THING 11 | // ^^^^^^^^^^^ definition 0.1.test `sg/initial`/OTHER_THING. 12 | // documentation 13 | // > ```go 14 | // > const OTHER_THING untyped int = 10 15 | // > ``` 16 | // ^^^^^^^^ reference 0.1.test `sg/initial`/MY_THING. 17 | 18 | func usesMyThing() { 19 | // ^^^^^^^^^^^ definition 0.1.test `sg/initial`/usesMyThing(). 20 | // documentation 21 | // > ```go 22 | // > func usesMyThing() 23 | // > ``` 24 | _ = MY_THING 25 | // ^^^^^^^^ reference 0.1.test `sg/initial`/MY_THING. 26 | } 27 | 28 | var initFunctions = map[string]int{} 29 | // ^^^^^^^^^^^^^ definition 0.1.test `sg/initial`/initFunctions. 30 | // documentation 31 | // > ```go 32 | // > var initFunctions map[string]int 33 | // > ``` 34 | 35 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/initial/type_declarations.go: -------------------------------------------------------------------------------- 1 | package initial 2 | // ^^^^^^^ reference 0.1.test `sg/initial`/ 3 | 4 | type LiteralType int 5 | // ^^^^^^^^^^^ definition 0.1.test `sg/initial`/LiteralType# 6 | // documentation 7 | // > ```go 8 | // > int 9 | // > ``` 10 | 11 | type FuncType func(LiteralType, int) bool 12 | // ^^^^^^^^ definition 0.1.test `sg/initial`/FuncType# 13 | // documentation 14 | // > ```go 15 | // > func(LiteralType, int) bool 16 | // > ``` 17 | // ^^^^^^^^^^^ reference 0.1.test `sg/initial`/LiteralType# 18 | 19 | type IfaceType interface { 20 | // ^^^^^^^^^ definition 0.1.test `sg/initial`/IfaceType# 21 | // documentation 22 | // > ```go 23 | // > type IfaceType interface 24 | // > ``` 25 | // documentation 26 | // > ```go 27 | // > interface { 28 | // > Method() LiteralType 29 | // > } 30 | // > ``` 31 | Method() LiteralType 32 | // ^^^^^^ definition 0.1.test `sg/initial`/IfaceType#Method. 33 | // documentation 34 | // > ```go 35 | // > func (IfaceType).Method() LiteralType 36 | // > ``` 37 | // ^^^^^^^^^^^ reference 0.1.test `sg/initial`/LiteralType# 38 | } 39 | 40 | type StructType struct { 41 | // ^^^^^^^^^^ definition 0.1.test `sg/initial`/StructType# 42 | // documentation 43 | // > ```go 44 | // > type StructType struct 45 | // > ``` 46 | // documentation 47 | // > ```go 48 | // > struct { 49 | // > m IfaceType 50 | // > f LiteralType 51 | // > anon struct { 52 | // > sub int 53 | // > } 54 | // > i interface { 55 | // > AnonMethod() bool 56 | // > } 57 | // > } 58 | // > ``` 59 | m IfaceType 60 | // ^ definition 0.1.test `sg/initial`/StructType#m. 61 | // documentation 62 | // > ```go 63 | // > struct field m sg/initial.IfaceType 64 | // > ``` 65 | // ^^^^^^^^^ reference 0.1.test `sg/initial`/IfaceType# 66 | f LiteralType 67 | // ^ definition 0.1.test `sg/initial`/StructType#f. 68 | // documentation 69 | // > ```go 70 | // > struct field f sg/initial.LiteralType 71 | // > ``` 72 | // ^^^^^^^^^^^ reference 0.1.test `sg/initial`/LiteralType# 73 | 74 | // anonymous struct 75 | anon struct { 76 | // ^^^^ definition 0.1.test `sg/initial`/StructType#anon. 77 | // documentation 78 | // > ```go 79 | // > struct field anon struct{sub int} 80 | // > ``` 81 | sub int 82 | // ^^^ definition 0.1.test `sg/initial`/StructType#anon.sub. 83 | // documentation 84 | // > ```go 85 | // > struct field sub int 86 | // > ``` 87 | } 88 | 89 | // interface within struct 90 | i interface { 91 | // ^ definition 0.1.test `sg/initial`/StructType#i. 92 | // documentation 93 | // > ```go 94 | // > struct field i interface{AnonMethod() bool} 95 | // > ``` 96 | AnonMethod() bool 97 | // ^^^^^^^^^^ definition 0.1.test `sg/initial`/StructType#i.AnonMethod. 98 | // documentation 99 | // > ```go 100 | // > func (interface).AnonMethod() bool 101 | // > ``` 102 | } 103 | } 104 | 105 | type DeclaredBefore struct{ DeclaredAfter } 106 | // ^^^^^^^^^^^^^^ definition 0.1.test `sg/initial`/DeclaredBefore# 107 | // documentation 108 | // > ```go 109 | // > type DeclaredBefore struct 110 | // > ``` 111 | // documentation 112 | // > ```go 113 | // > struct { 114 | // > DeclaredAfter 115 | // > } 116 | // > ``` 117 | // ^^^^^^^^^^^^^ definition 0.1.test `sg/initial`/DeclaredBefore#DeclaredAfter. 118 | // documentation 119 | // > ```go 120 | // > struct field DeclaredAfter sg/initial.DeclaredAfter 121 | // > ``` 122 | // ^^^^^^^^^^^^^ reference 0.1.test `sg/initial`/DeclaredAfter# 123 | type DeclaredAfter struct{} 124 | // ^^^^^^^^^^^^^ definition 0.1.test `sg/initial`/DeclaredAfter# 125 | // documentation 126 | // > ```go 127 | // > type DeclaredAfter struct 128 | // > ``` 129 | // documentation 130 | // > ```go 131 | // > struct{} 132 | // > ``` 133 | 134 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/initial/type_hovers.go: -------------------------------------------------------------------------------- 1 | package initial 2 | // ^^^^^^^ reference 0.1.test `sg/initial`/ 3 | 4 | type ( 5 | // HoverTypeList is a cool struct 6 | HoverTypeList struct{} 7 | // ^^^^^^^^^^^^^ definition 0.1.test `sg/initial`/HoverTypeList# 8 | // documentation 9 | // > ```go 10 | // > type HoverTypeList struct 11 | // > ``` 12 | // documentation 13 | // > ```go 14 | // > struct{} 15 | // > ``` 16 | ) 17 | 18 | // This should show up as well 19 | type HoverType struct{} 20 | // ^^^^^^^^^ definition 0.1.test `sg/initial`/HoverType# 21 | // documentation 22 | // > ```go 23 | // > type HoverType struct 24 | // > ``` 25 | // documentation 26 | // > This should show up as well 27 | // documentation 28 | // > ```go 29 | // > struct{} 30 | // > ``` 31 | 32 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/inlinestruct/inlinestruct.go: -------------------------------------------------------------------------------- 1 | package inlinestruct 2 | // ^^^^^^^^^^^^ definition 0.1.test `sg/inlinestruct`/ 3 | // documentation 4 | // > package inlinestruct 5 | 6 | type FieldInterface interface { 7 | // ^^^^^^^^^^^^^^ definition 0.1.test `sg/inlinestruct`/FieldInterface# 8 | // documentation 9 | // > ```go 10 | // > type FieldInterface interface 11 | // > ``` 12 | // documentation 13 | // > ```go 14 | // > interface { 15 | // > SomeMethod() string 16 | // > } 17 | // > ``` 18 | SomeMethod() string 19 | // ^^^^^^^^^^ definition 0.1.test `sg/inlinestruct`/FieldInterface#SomeMethod. 20 | // documentation 21 | // > ```go 22 | // > func (FieldInterface).SomeMethod() string 23 | // > ``` 24 | } 25 | 26 | var MyInline = struct { 27 | // ^^^^^^^^ definition 0.1.test `sg/inlinestruct`/MyInline. 28 | // documentation 29 | // > ```go 30 | // > var MyInline struct{privateField FieldInterface; PublicField FieldInterface} 31 | // > ``` 32 | privateField FieldInterface 33 | // ^^^^^^^^^^^^ definition 0.1.test `sg/inlinestruct`/MyInline:privateField. 34 | // documentation 35 | // > ```go 36 | // > struct field privateField sg/inlinestruct.FieldInterface 37 | // > ``` 38 | // ^^^^^^^^^^^^^^ reference 0.1.test `sg/inlinestruct`/FieldInterface# 39 | PublicField FieldInterface 40 | // ^^^^^^^^^^^ definition 0.1.test `sg/inlinestruct`/MyInline:PublicField. 41 | // documentation 42 | // > ```go 43 | // > struct field PublicField sg/inlinestruct.FieldInterface 44 | // > ``` 45 | // ^^^^^^^^^^^^^^ reference 0.1.test `sg/inlinestruct`/FieldInterface# 46 | }{} 47 | 48 | func MyFunc() { 49 | // ^^^^^^ definition 0.1.test `sg/inlinestruct`/MyFunc(). 50 | // documentation 51 | // > ```go 52 | // > func MyFunc() 53 | // > ``` 54 | _ = MyInline.privateField 55 | // ^^^^^^^^ reference 0.1.test `sg/inlinestruct`/MyInline. 56 | // ^^^^^^^^^^^^ reference 0.1.test `sg/inlinestruct`/MyInline:privateField. 57 | _ = MyInline.PublicField 58 | // ^^^^^^^^ reference 0.1.test `sg/inlinestruct`/MyInline. 59 | // ^^^^^^^^^^^ reference 0.1.test `sg/inlinestruct`/MyInline:PublicField. 60 | } 61 | 62 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/inlinestruct/inlinestruct_func.go: -------------------------------------------------------------------------------- 1 | package inlinestruct 2 | // ^^^^^^^^^^^^ reference 0.1.test `sg/inlinestruct`/ 3 | 4 | type InFuncSig struct { 5 | // ^^^^^^^^^ definition 0.1.test `sg/inlinestruct`/InFuncSig# 6 | // documentation 7 | // > ```go 8 | // > type InFuncSig struct 9 | // > ``` 10 | // documentation 11 | // > ```go 12 | // > struct { 13 | // > value bool 14 | // > } 15 | // > ``` 16 | value bool 17 | // ^^^^^ definition 0.1.test `sg/inlinestruct`/InFuncSig#value. 18 | // documentation 19 | // > ```go 20 | // > struct field value bool 21 | // > ``` 22 | } 23 | 24 | var rowsCloseHook = func() func(InFuncSig, *error) { return nil } 25 | // ^^^^^^^^^^^^^ definition 0.1.test `sg/inlinestruct`/rowsCloseHook. 26 | // documentation 27 | // > ```go 28 | // > var rowsCloseHook func() func(InFuncSig, *error) 29 | // > ``` 30 | // ^^^^^^^^^ reference 0.1.test `sg/inlinestruct`/InFuncSig# 31 | 32 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/inlinestruct/inlinestruct_genericindex.go: -------------------------------------------------------------------------------- 1 | package inlinestruct 2 | // ^^^^^^^^^^^^ reference 0.1.test `sg/inlinestruct`/ 3 | 4 | type Processor[T any] interface { 5 | // ^^^^^^^^^ definition 0.1.test `sg/inlinestruct`/Processor# 6 | // documentation 7 | // > ```go 8 | // > type Processor interface 9 | // > ``` 10 | // documentation 11 | // > ```go 12 | // > interface { 13 | // > Process(payload T) 14 | // > ProcessorType() string 15 | // > } 16 | // > ``` 17 | // ^ definition local 0 18 | Process(payload T) 19 | // ^^^^^^^ definition 0.1.test `sg/inlinestruct`/Processor#Process. 20 | // documentation 21 | // > ```go 22 | // > func (Processor[T any]).Process(payload T) 23 | // > ``` 24 | // ^^^^^^^ definition local 1 25 | // ^ reference local 0 26 | ProcessorType() string 27 | // ^^^^^^^^^^^^^ definition 0.1.test `sg/inlinestruct`/Processor#ProcessorType. 28 | // documentation 29 | // > ```go 30 | // > func (Processor[T any]).ProcessorType() string 31 | // > ``` 32 | } 33 | 34 | type Limit int 35 | // ^^^^^ definition 0.1.test `sg/inlinestruct`/Limit# 36 | // documentation 37 | // > ```go 38 | // > int 39 | // > ``` 40 | 41 | type ProcessImpl struct{} 42 | // ^^^^^^^^^^^ definition 0.1.test `sg/inlinestruct`/ProcessImpl# 43 | // documentation 44 | // > ```go 45 | // > type ProcessImpl struct 46 | // > ``` 47 | // documentation 48 | // > ```go 49 | // > struct{} 50 | // > ``` 51 | 52 | func (p *ProcessImpl) Process(payload Limit) { panic("not implemented") } 53 | // ^ definition local 2 54 | // ^^^^^^^^^^^ reference 0.1.test `sg/inlinestruct`/ProcessImpl# 55 | // ^^^^^^^ definition 0.1.test `sg/inlinestruct`/ProcessImpl#Process(). 56 | // documentation 57 | // > ```go 58 | // > func (*ProcessImpl).Process(payload Limit) 59 | // > ``` 60 | // ^^^^^^^ definition local 3 61 | // ^^^^^ reference 0.1.test `sg/inlinestruct`/Limit# 62 | func (p *ProcessImpl) ProcessorType() string { panic("not implemented") } 63 | // ^ definition local 4 64 | // ^^^^^^^^^^^ reference 0.1.test `sg/inlinestruct`/ProcessImpl# 65 | // ^^^^^^^^^^^^^ definition 0.1.test `sg/inlinestruct`/ProcessImpl#ProcessorType(). 66 | // documentation 67 | // > ```go 68 | // > func (*ProcessImpl).ProcessorType() string 69 | // > ``` 70 | 71 | var _ Processor[Limit] = &ProcessImpl{} 72 | // ^^^^^^^^^ reference 0.1.test `sg/inlinestruct`/Processor# 73 | // ^^^^^ reference 0.1.test `sg/inlinestruct`/Limit# 74 | // ^^^^^^^^^^^ reference 0.1.test `sg/inlinestruct`/ProcessImpl# 75 | 76 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/inlinestruct/inlinestruct_interface.go: -------------------------------------------------------------------------------- 1 | package inlinestruct 2 | // ^^^^^^^^^^^^ reference 0.1.test `sg/inlinestruct`/ 3 | 4 | import "context" 5 | // ^^^^^^^ reference github.com/golang/go/src go1.22 context/ 6 | 7 | func Target() interface { 8 | // ^^^^^^ definition 0.1.test `sg/inlinestruct`/Target(). 9 | // documentation 10 | // > ```go 11 | // > func Target() interface{AbbreviatedOID(Context) (string, error); Commit(Context) (string, error); OID(Context) (int, error); Type(Context) (int, error)} 12 | // > ``` 13 | OID(context.Context) (int, error) 14 | // ^^^ definition 0.1.test `sg/inlinestruct`/func:Target:OID(). 15 | // documentation 16 | // > ```go 17 | // > func (interface).OID(Context) (int, error) 18 | // > ``` 19 | // ^^^^^^^ reference github.com/golang/go/src go1.22 context/ 20 | // ^^^^^^^ reference github.com/golang/go/src go1.22 context/Context# 21 | AbbreviatedOID(context.Context) (string, error) 22 | // ^^^^^^^^^^^^^^ definition 0.1.test `sg/inlinestruct`/func:Target:AbbreviatedOID(). 23 | // documentation 24 | // > ```go 25 | // > func (interface).AbbreviatedOID(Context) (string, error) 26 | // > ``` 27 | // ^^^^^^^ reference github.com/golang/go/src go1.22 context/ 28 | // ^^^^^^^ reference github.com/golang/go/src go1.22 context/Context# 29 | Commit(context.Context) (string, error) 30 | // ^^^^^^ definition 0.1.test `sg/inlinestruct`/func:Target:Commit(). 31 | // documentation 32 | // > ```go 33 | // > func (interface).Commit(Context) (string, error) 34 | // > ``` 35 | // ^^^^^^^ reference github.com/golang/go/src go1.22 context/ 36 | // ^^^^^^^ reference github.com/golang/go/src go1.22 context/Context# 37 | Type(context.Context) (int, error) 38 | // ^^^^ definition 0.1.test `sg/inlinestruct`/func:Target:Type(). 39 | // documentation 40 | // > ```go 41 | // > func (interface).Type(Context) (int, error) 42 | // > ``` 43 | // ^^^^^^^ reference github.com/golang/go/src go1.22 context/ 44 | // ^^^^^^^ reference github.com/golang/go/src go1.22 context/Context# 45 | } { 46 | panic("not implemented") 47 | } 48 | 49 | func something() { 50 | // ^^^^^^^^^ definition 0.1.test `sg/inlinestruct`/something(). 51 | // documentation 52 | // > ```go 53 | // > func something() 54 | // > ``` 55 | x := Target() 56 | // ^ definition local 0 57 | // ^^^^^^ reference 0.1.test `sg/inlinestruct`/Target(). 58 | x.OID(context.Background()) 59 | // ^ reference local 0 60 | // ^^^ reference 0.1.test `sg/inlinestruct`/func:Target:OID(). 61 | // ^^^^^^^ reference github.com/golang/go/src go1.22 context/ 62 | // ^^^^^^^^^^ reference github.com/golang/go/src go1.22 context/Background(). 63 | } 64 | 65 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/inlinestruct/inlinestruct_map.go: -------------------------------------------------------------------------------- 1 | package inlinestruct 2 | // ^^^^^^^^^^^^ reference 0.1.test `sg/inlinestruct`/ 3 | 4 | var testHook = func(map[string]string) {} 5 | // ^^^^^^^^ definition 0.1.test `sg/inlinestruct`/testHook. 6 | // documentation 7 | // > ```go 8 | // > var testHook func(map[string]string) 9 | // > ``` 10 | 11 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/inlinestruct/inlinestruct_multivar.go: -------------------------------------------------------------------------------- 1 | package inlinestruct 2 | // ^^^^^^^^^^^^ reference 0.1.test `sg/inlinestruct`/ 3 | 4 | type Params struct{} 5 | // ^^^^^^ definition 0.1.test `sg/inlinestruct`/Params# 6 | // documentation 7 | // > ```go 8 | // > type Params struct 9 | // > ``` 10 | // documentation 11 | // > ```go 12 | // > struct{} 13 | // > ``` 14 | type HighlightedCode struct{} 15 | // ^^^^^^^^^^^^^^^ definition 0.1.test `sg/inlinestruct`/HighlightedCode# 16 | // documentation 17 | // > ```go 18 | // > type HighlightedCode struct 19 | // > ``` 20 | // documentation 21 | // > ```go 22 | // > struct{} 23 | // > ``` 24 | 25 | var Mocks, emptyMocks struct { 26 | // ^^^^^ definition 0.1.test `sg/inlinestruct`/Mocks. 27 | // documentation 28 | // > ```go 29 | // > var Mocks struct{Code func(p Params) (response *HighlightedCode, aborted bool, err error)} 30 | // > ``` 31 | // ^^^^^^^^^^ definition 0.1.test `sg/inlinestruct`/emptyMocks. 32 | // documentation 33 | // > ```go 34 | // > var emptyMocks struct{Code func(p Params) (response *HighlightedCode, aborted bool, err error)} 35 | // > ``` 36 | Code func(p Params) (response *HighlightedCode, aborted bool, err error) 37 | // ^^^^ definition 0.1.test `sg/inlinestruct`/inline-6-5:Code. 38 | // documentation 39 | // > ```go 40 | // > struct field Code func(p sg/inlinestruct.Params) (response *sg/inlinestruct.HighlightedCode, aborted bool, err error) 41 | // > ``` 42 | // ^ definition local 0 43 | // ^^^^^^ reference 0.1.test `sg/inlinestruct`/Params# 44 | // ^^^^^^^^ definition local 1 45 | // ^^^^^^^^^^^^^^^ reference 0.1.test `sg/inlinestruct`/HighlightedCode# 46 | // ^^^^^^^ definition local 2 47 | // ^^^ definition local 3 48 | } 49 | 50 | var MocksSingle struct { 51 | // ^^^^^^^^^^^ definition 0.1.test `sg/inlinestruct`/MocksSingle. 52 | // documentation 53 | // > ```go 54 | // > var MocksSingle struct{Code func(p Params) (response *HighlightedCode, aborted bool, err error)} 55 | // > ``` 56 | Code func(p Params) (response *HighlightedCode, aborted bool, err error) 57 | // ^^^^ definition 0.1.test `sg/inlinestruct`/MocksSingle:Code. 58 | // documentation 59 | // > ```go 60 | // > struct field Code func(p sg/inlinestruct.Params) (response *sg/inlinestruct.HighlightedCode, aborted bool, err error) 61 | // > ``` 62 | // ^ definition local 4 63 | // ^^^^^^ reference 0.1.test `sg/inlinestruct`/Params# 64 | // ^^^^^^^^ definition local 5 65 | // ^^^^^^^^^^^^^^^ reference 0.1.test `sg/inlinestruct`/HighlightedCode# 66 | // ^^^^^^^ definition local 6 67 | // ^^^ definition local 7 68 | } 69 | 70 | var ( 71 | okReply interface{} = "OK" 72 | // ^^^^^^^ definition 0.1.test `sg/inlinestruct`/okReply. 73 | // documentation 74 | // > ```go 75 | // > var okReply interface{} 76 | // > ``` 77 | pongReply interface{} = "PONG" 78 | // ^^^^^^^^^ definition 0.1.test `sg/inlinestruct`/pongReply. 79 | // documentation 80 | // > ```go 81 | // > var pongReply interface{} 82 | // > ``` 83 | ) 84 | 85 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/package-documentation/primary.go: -------------------------------------------------------------------------------- 1 | // This is documentation for this package. 2 | package packagedocumentation 3 | // ^^^^^^^^^^^^^^^^^^^^ definition github.com/weightylarva/scip-go . `github.com/weightylarva/scip-go/internal/testdata/snapshots/input/package-documentation`/ 4 | // documentation 5 | // > This is documentation for this package. 6 | 7 | func Exported() {} 8 | // ^^^^^^^^ definition github.com/weightylarva/scip-go . `github.com/weightylarva/scip-go/internal/testdata/snapshots/input/package-documentation`/Exported(). 9 | // documentation 10 | // > ```go 11 | // > func Exported() 12 | // > ``` 13 | 14 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/package-documentation/secondary.go: -------------------------------------------------------------------------------- 1 | package packagedocumentation 2 | // ^^^^^^^^^^^^^^^^^^^^ reference github.com/weightylarva/scip-go . `github.com/weightylarva/scip-go/internal/testdata/snapshots/input/package-documentation`/ 3 | 4 | func AlsoExporter() {} 5 | // ^^^^^^^^^^^^ definition github.com/weightylarva/scip-go . `github.com/weightylarva/scip-go/internal/testdata/snapshots/input/package-documentation`/AlsoExporter(). 6 | // documentation 7 | // > ```go 8 | // > func AlsoExporter() 9 | // > ``` 10 | 11 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/replace-directives/replace_directives.go: -------------------------------------------------------------------------------- 1 | package replacers 2 | // ^^^^^^^^^ definition 0.1.test `sg/replace-directives`/ 3 | // documentation 4 | // > package replacers 5 | 6 | import ( 7 | "fmt" 8 | // ^^^ reference github.com/golang/go/src go1.22 fmt/ 9 | 10 | "github.com/dghubble/gologin" 11 | // ^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference github.com/sourcegraph/gologin c6f1b62954d8 `github.com/dghubble/gologin`/ 12 | ) 13 | 14 | func Something() { 15 | // ^^^^^^^^^ definition 0.1.test `sg/replace-directives`/Something(). 16 | // documentation 17 | // > ```go 18 | // > func Something() 19 | // > ``` 20 | fmt.Println(gologin.DefaultCookieConfig) 21 | // ^^^ reference github.com/golang/go/src go1.22 fmt/ 22 | // ^^^^^^^ reference github.com/golang/go/src go1.22 fmt/Println(). 23 | // ^^^^^^^ reference github.com/sourcegraph/gologin c6f1b62954d8 `github.com/dghubble/gologin`/ 24 | // ^^^^^^^^^^^^^^^^^^^ reference github.com/sourcegraph/gologin c6f1b62954d8 `github.com/dghubble/gologin`/DefaultCookieConfig. 25 | } 26 | 27 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/sharedtestmodule/cmd/gitserver/server/cleanup.go: -------------------------------------------------------------------------------- 1 | package server 2 | // ^^^^^^ reference 0.1.test `sg/sharedtestmodule/cmd/gitserver/server`/ 3 | 4 | func LiterallyAnything() {} 5 | // ^^^^^^^^^^^^^^^^^ definition 0.1.test `sg/sharedtestmodule/cmd/gitserver/server`/LiterallyAnything(). 6 | // documentation 7 | // > ```go 8 | // > func LiterallyAnything() 9 | // > ``` 10 | 11 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/sharedtestmodule/cmd/gitserver/server/cleanup_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | // ^^^^^^ reference 0.1.test `sg/sharedtestmodule/cmd/gitserver/server`/ 3 | 4 | import "testing" 5 | // ^^^^^^^ reference github.com/golang/go/src go1.22 testing/ 6 | 7 | func TestStuff(t *testing.T) { 8 | // ^^^^^^^^^ definition 0.1.test `sg/sharedtestmodule/cmd/gitserver/server`/TestStuff(). 9 | // documentation 10 | // > ```go 11 | // > func TestStuff(t *T) 12 | // > ``` 13 | // ^ definition local 0 14 | // ^^^^^^^ reference github.com/golang/go/src go1.22 testing/ 15 | // ^ reference github.com/golang/go/src go1.22 testing/T# 16 | wd := "hello" 17 | // ^^ definition local 1 18 | repo := "world" 19 | // ^^^^ definition local 2 20 | 21 | runCmd(t, wd, "git", "init", repo) 22 | // ^^^^^^ reference 0.1.test `sg/sharedtestmodule/cmd/gitserver/server`/runCmd(). 23 | // ^ reference local 0 24 | // ^^ reference local 1 25 | // ^^^^ reference local 2 26 | } 27 | 28 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/sharedtestmodule/cmd/gitserver/server/server.go: -------------------------------------------------------------------------------- 1 | package server 2 | // ^^^^^^ definition 0.1.test `sg/sharedtestmodule/cmd/gitserver/server`/ 3 | // documentation 4 | // > package server 5 | 6 | func AnythingAtAll() {} 7 | // ^^^^^^^^^^^^^ definition 0.1.test `sg/sharedtestmodule/cmd/gitserver/server`/AnythingAtAll(). 8 | // documentation 9 | // > ```go 10 | // > func AnythingAtAll() 11 | // > ``` 12 | 13 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/sharedtestmodule/cmd/gitserver/server/server_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | // ^^^^^^ reference 0.1.test `sg/sharedtestmodule/cmd/gitserver/server`/ 3 | 4 | import "testing" 5 | // ^^^^^^^ reference github.com/golang/go/src go1.22 testing/ 6 | 7 | func TestExecRequest(t *testing.T) { 8 | // ^^^^^^^^^^^^^^^ definition 0.1.test `sg/sharedtestmodule/cmd/gitserver/server`/TestExecRequest(). 9 | // documentation 10 | // > ```go 11 | // > func TestExecRequest(t *T) 12 | // > ``` 13 | // ^ definition local 0 14 | // ^^^^^^^ reference github.com/golang/go/src go1.22 testing/ 15 | // ^ reference github.com/golang/go/src go1.22 testing/T# 16 | t.Log("hello world") 17 | // ^ reference local 0 18 | // ^^^ reference github.com/golang/go/src go1.22 testing/common#Log(). 19 | } 20 | 21 | func runCmd(t *testing.T, dir string, cmd string, arg ...string) {} 22 | // ^^^^^^ definition 0.1.test `sg/sharedtestmodule/cmd/gitserver/server`/runCmd(). 23 | // documentation 24 | // > ```go 25 | // > func runCmd(t *T, dir string, cmd string, arg ...string) 26 | // > ``` 27 | // ^ definition local 1 28 | // ^^^^^^^ reference github.com/golang/go/src go1.22 testing/ 29 | // ^ reference github.com/golang/go/src go1.22 testing/T# 30 | // ^^^ definition local 2 31 | // ^^^ definition local 3 32 | // ^^^ definition local 4 33 | 34 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/switches/switches.go: -------------------------------------------------------------------------------- 1 | package switches 2 | // ^^^^^^^^ definition 0.1.test `sg/switches`/ 3 | // documentation 4 | // > package switches 5 | 6 | // CustomSwitch does the things in a switch 7 | type CustomSwitch struct{} 8 | // ^^^^^^^^^^^^ definition 0.1.test `sg/switches`/CustomSwitch# 9 | // documentation 10 | // > ```go 11 | // > type CustomSwitch struct 12 | // > ``` 13 | // documentation 14 | // > CustomSwitch does the things in a switch 15 | // documentation 16 | // > ```go 17 | // > struct{} 18 | // > ``` 19 | 20 | // Something does some things... and stuff 21 | func (c *CustomSwitch) Something() bool { return false } 22 | // ^ definition local 0 23 | // ^^^^^^^^^^^^ reference 0.1.test `sg/switches`/CustomSwitch# 24 | // ^^^^^^^^^ definition 0.1.test `sg/switches`/CustomSwitch#Something(). 25 | // documentation 26 | // > ```go 27 | // > func (*CustomSwitch).Something() bool 28 | // > ``` 29 | // documentation 30 | // > Something does some things... and stuff 31 | 32 | func Switch(interfaceValue interface{}) bool { 33 | // ^^^^^^ definition 0.1.test `sg/switches`/Switch(). 34 | // documentation 35 | // > ```go 36 | // > func Switch(interfaceValue interface{}) bool 37 | // > ``` 38 | // ^^^^^^^^^^^^^^ definition local 1 39 | switch concreteValue := interfaceValue.(type) { 40 | // ^^^^^^^^^^^^^ definition local 2 41 | // ^^^^^^^^^^^^^^ reference local 1 42 | case int: 43 | return concreteValue*3 > 10 44 | // ^^^^^^^^^^^^^ reference local 2 45 | // override_documentation 46 | // > ```go 47 | // > int 48 | // > ``` 49 | case bool: 50 | return !concreteValue 51 | // ^^^^^^^^^^^^^ reference local 2 52 | // override_documentation 53 | // > ```go 54 | // > bool 55 | // > ``` 56 | case CustomSwitch: 57 | // ^^^^^^^^^^^^ reference 0.1.test `sg/switches`/CustomSwitch# 58 | return concreteValue.Something() 59 | // ^^^^^^^^^^^^^ reference local 2 60 | // override_documentation 61 | // > ```go 62 | // > sg/switches.CustomSwitch 63 | // > ``` 64 | // ^^^^^^^^^ reference 0.1.test `sg/switches`/CustomSwitch#Something(). 65 | default: 66 | return false 67 | } 68 | } 69 | 70 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/testdata/cmd/minimal_main/minimal_main.go: -------------------------------------------------------------------------------- 1 | package main 2 | // ^^^^ definition 0.1.test `sg/testdata/cmd/minimal_main`/ 3 | // documentation 4 | // > package main 5 | 6 | type User struct { 7 | // ^^^^ definition 0.1.test `sg/testdata/cmd/minimal_main`/User# 8 | // documentation 9 | // > ```go 10 | // > type User struct 11 | // > ``` 12 | // documentation 13 | // > ```go 14 | // > struct { 15 | // > Id string 16 | // > Name string 17 | // > } 18 | // > ``` 19 | Id, Name string 20 | // ^^ definition 0.1.test `sg/testdata/cmd/minimal_main`/User#Id. 21 | // documentation 22 | // > ```go 23 | // > struct field Id string 24 | // > ``` 25 | // ^^^^ definition 0.1.test `sg/testdata/cmd/minimal_main`/User#Name. 26 | // documentation 27 | // > ```go 28 | // > struct field Name string 29 | // > ``` 30 | } 31 | 32 | type UserResource struct{} 33 | // ^^^^^^^^^^^^ definition 0.1.test `sg/testdata/cmd/minimal_main`/UserResource# 34 | // documentation 35 | // > ```go 36 | // > type UserResource struct 37 | // > ``` 38 | // documentation 39 | // > ```go 40 | // > struct{} 41 | // > ``` 42 | 43 | func main() {} 44 | // ^^^^ definition 0.1.test `sg/testdata/cmd/minimal_main`/main(). 45 | // documentation 46 | // > ```go 47 | // > func main() 48 | // > ``` 49 | 50 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/testdata/conflicting_test_symbols/sandbox_unsupported_test.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !windows && !freebsd 2 | // +build !linux,!windows,!freebsd 3 | 4 | package osl 5 | // ^^^ definition 0.1.test `sg/testdata/conflicting_test_symbols`/ 6 | // documentation 7 | // > package osl 8 | 9 | import ( 10 | "errors" 11 | // ^^^^^^ reference github.com/golang/go/src go1.22 errors/ 12 | "testing" 13 | // ^^^^^^^ reference github.com/golang/go/src go1.22 testing/ 14 | ) 15 | 16 | var ErrNotImplemented = errors.New("not implemented") 17 | // ^^^^^^^^^^^^^^^^^ definition 0.1.test `sg/testdata/conflicting_test_symbols`/ErrNotImplemented. 18 | // documentation 19 | // > ```go 20 | // > var ErrNotImplemented error 21 | // > ``` 22 | // ^^^^^^ reference github.com/golang/go/src go1.22 errors/ 23 | // ^^^ reference github.com/golang/go/src go1.22 errors/New(). 24 | 25 | func newKey(t *testing.T) (string, error) { 26 | // ^^^^^^ definition 0.1.test `sg/testdata/conflicting_test_symbols`/newKey(). 27 | // documentation 28 | // > ```go 29 | // > func newKey(t *T) (string, error) 30 | // > ``` 31 | // ^ definition local 0 32 | // ^^^^^^^ reference github.com/golang/go/src go1.22 testing/ 33 | // ^ reference github.com/golang/go/src go1.22 testing/T# 34 | return "", ErrNotImplemented 35 | // ^^^^^^^^^^^^^^^^^ reference 0.1.test `sg/testdata/conflicting_test_symbols`/ErrNotImplemented. 36 | } 37 | 38 | func verifySandbox(t *testing.T, s string) { 39 | // ^^^^^^^^^^^^^ definition 0.1.test `sg/testdata/conflicting_test_symbols`/verifySandbox(). 40 | // documentation 41 | // > ```go 42 | // > func verifySandbox(t *T, s string) 43 | // > ``` 44 | // ^ definition local 1 45 | // ^^^^^^^ reference github.com/golang/go/src go1.22 testing/ 46 | // ^ reference github.com/golang/go/src go1.22 testing/T# 47 | // ^ definition local 2 48 | return 49 | } 50 | 51 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/testdata/duplicate_path_id/main.go: -------------------------------------------------------------------------------- 1 | package gosrc 2 | // ^^^^^ reference 0.1.test `sg/testdata/duplicate_path_id`/ 3 | 4 | type importMeta struct{} 5 | // ^^^^^^^^^^ definition 0.1.test `sg/testdata/duplicate_path_id`/importMeta# 6 | // documentation 7 | // > ```go 8 | // > type importMeta struct 9 | // > ``` 10 | // documentation 11 | // > ```go 12 | // > struct{} 13 | // > ``` 14 | 15 | type sourceMeta struct{} 16 | // ^^^^^^^^^^ definition 0.1.test `sg/testdata/duplicate_path_id`/sourceMeta# 17 | // documentation 18 | // > ```go 19 | // > type sourceMeta struct 20 | // > ``` 21 | // documentation 22 | // > ```go 23 | // > struct{} 24 | // > ``` 25 | 26 | func fetchMeta() (string, *importMeta, *sourceMeta) { 27 | // ^^^^^^^^^ definition 0.1.test `sg/testdata/duplicate_path_id`/fetchMeta(). 28 | // documentation 29 | // > ```go 30 | // > func fetchMeta() (string, *importMeta, *sourceMeta) 31 | // > ``` 32 | // ^^^^^^^^^^ reference 0.1.test `sg/testdata/duplicate_path_id`/importMeta# 33 | // ^^^^^^^^^^ reference 0.1.test `sg/testdata/duplicate_path_id`/sourceMeta# 34 | panic("hmm") 35 | } 36 | 37 | func init() {} 38 | // ^^^^ definition 0.1.test `sg/testdata/duplicate_path_id`/init(). 39 | // documentation 40 | // > ```go 41 | // > func init() 42 | // > ``` 43 | func init() {} 44 | // ^^^^ definition 0.1.test `sg/testdata/duplicate_path_id`/init(). 45 | // documentation 46 | // > ```go 47 | // > func init() 48 | // > ``` 49 | func init() {} 50 | // ^^^^ definition 0.1.test `sg/testdata/duplicate_path_id`/init(). 51 | // documentation 52 | // > ```go 53 | // > func init() 54 | // > ``` 55 | 56 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/testdata/duplicate_path_id/two.go: -------------------------------------------------------------------------------- 1 | package gosrc 2 | // ^^^^^ definition 0.1.test `sg/testdata/duplicate_path_id`/ 3 | // documentation 4 | // > package gosrc 5 | 6 | func init() {} 7 | // ^^^^ definition 0.1.test `sg/testdata/duplicate_path_id`/init(). 8 | // documentation 9 | // > ```go 10 | // > func init() 11 | // > ``` 12 | 13 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/testdata/external_composite.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | // ^^^^^^^^ reference 0.1.test `sg/testdata`/ 3 | 4 | import "net/http" 5 | // ^^^^^^^^ reference github.com/golang/go/src go1.22 `net/http`/ 6 | 7 | type NestedHandler struct { 8 | // ^^^^^^^^^^^^^ definition 0.1.test `sg/testdata`/NestedHandler# 9 | // documentation 10 | // > ```go 11 | // > type NestedHandler struct 12 | // > ``` 13 | // documentation 14 | // > ```go 15 | // > struct { 16 | // > Handler 17 | // > Other int 18 | // > } 19 | // > ``` 20 | // relationship github.com/golang/go/src go1.22 `net/http`/Handler# implementation 21 | http.Handler 22 | // ^^^^ reference github.com/golang/go/src go1.22 `net/http`/ 23 | // ^^^^^^^ definition 0.1.test `sg/testdata`/NestedHandler#Handler. 24 | // documentation 25 | // > ```go 26 | // > struct field Handler net/http.Handler 27 | // > ``` 28 | // ^^^^^^^ reference github.com/golang/go/src go1.22 `net/http`/Handler# 29 | Other int 30 | // ^^^^^ definition 0.1.test `sg/testdata`/NestedHandler#Other. 31 | // documentation 32 | // > ```go 33 | // > struct field Other int 34 | // > ``` 35 | } 36 | 37 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/testdata/implementations_embedded.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | // ^^^^^^^^ reference 0.1.test `sg/testdata`/ 3 | 4 | import "io" 5 | // ^^ reference github.com/golang/go/src go1.22 io/ 6 | 7 | type I3 interface { 8 | // ^^ definition 0.1.test `sg/testdata`/I3# 9 | // documentation 10 | // > ```go 11 | // > type I3 interface 12 | // > ``` 13 | // documentation 14 | // > ```go 15 | // > interface { 16 | // > Close() error 17 | // > } 18 | // > ``` 19 | Close() error 20 | // ^^^^^ definition 0.1.test `sg/testdata`/I3#Close. 21 | // documentation 22 | // > ```go 23 | // > func (I3).Close() error 24 | // > ``` 25 | } 26 | 27 | type TClose struct { 28 | // ^^^^^^ definition 0.1.test `sg/testdata`/TClose# 29 | // documentation 30 | // > ```go 31 | // > type TClose struct 32 | // > ``` 33 | // documentation 34 | // > ```go 35 | // > struct { 36 | // > Closer 37 | // > } 38 | // > ``` 39 | // relationship github.com/golang/go/src go1.22 io/Closer# implementation 40 | // relationship 0.1.test `sg/testdata`/I3# implementation 41 | io.Closer 42 | // ^^ reference github.com/golang/go/src go1.22 io/ 43 | // ^^^^^^ definition 0.1.test `sg/testdata`/TClose#Closer. 44 | // documentation 45 | // > ```go 46 | // > struct field Closer io.Closer 47 | // > ``` 48 | // ^^^^^^ reference github.com/golang/go/src go1.22 io/Closer# 49 | } 50 | 51 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/testdata/implementations_methods.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | // ^^^^^^^^ reference 0.1.test `sg/testdata`/ 3 | 4 | type InterfaceWithSingleMethod interface { 5 | // ^^^^^^^^^^^^^^^^^^^^^^^^^ definition 0.1.test `sg/testdata`/InterfaceWithSingleMethod# 6 | // documentation 7 | // > ```go 8 | // > type InterfaceWithSingleMethod interface 9 | // > ``` 10 | // documentation 11 | // > ```go 12 | // > interface { 13 | // > SingleMethod() float64 14 | // > } 15 | // > ``` 16 | SingleMethod() float64 17 | // ^^^^^^^^^^^^ definition 0.1.test `sg/testdata`/InterfaceWithSingleMethod#SingleMethod. 18 | // documentation 19 | // > ```go 20 | // > func (InterfaceWithSingleMethod).SingleMethod() float64 21 | // > ``` 22 | } 23 | 24 | type StructWithMethods struct{} 25 | // ^^^^^^^^^^^^^^^^^ definition 0.1.test `sg/testdata`/StructWithMethods# 26 | // documentation 27 | // > ```go 28 | // > type StructWithMethods struct 29 | // > ``` 30 | // documentation 31 | // > ```go 32 | // > struct{} 33 | // > ``` 34 | // relationship 0.1.test `sg/testdata`/InterfaceWithSingleMethod# implementation 35 | 36 | func (StructWithMethods) SingleMethod() float64 { return 5.0 } 37 | // ^^^^^^^^^^^^^^^^^ reference 0.1.test `sg/testdata`/StructWithMethods# 38 | // ^^^^^^^^^^^^ definition 0.1.test `sg/testdata`/StructWithMethods#SingleMethod(). 39 | // documentation 40 | // > ```go 41 | // > func (StructWithMethods).SingleMethod() float64 42 | // > ``` 43 | // relationship 0.1.test `sg/testdata`/InterfaceWithSingleMethod#SingleMethod. implementation 44 | 45 | type InterfaceWithSingleMethodTwoImplementers interface { 46 | // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition 0.1.test `sg/testdata`/InterfaceWithSingleMethodTwoImplementers# 47 | // documentation 48 | // > ```go 49 | // > type InterfaceWithSingleMethodTwoImplementers interface 50 | // > ``` 51 | // documentation 52 | // > ```go 53 | // > interface { 54 | // > SingleMethodTwoImpl() float64 55 | // > } 56 | // > ``` 57 | SingleMethodTwoImpl() float64 58 | // ^^^^^^^^^^^^^^^^^^^ definition 0.1.test `sg/testdata`/InterfaceWithSingleMethodTwoImplementers#SingleMethodTwoImpl. 59 | // documentation 60 | // > ```go 61 | // > func (InterfaceWithSingleMethodTwoImplementers).SingleMethodTwoImpl() float64 62 | // > ``` 63 | } 64 | 65 | type TwoImplOne struct{} 66 | // ^^^^^^^^^^ definition 0.1.test `sg/testdata`/TwoImplOne# 67 | // documentation 68 | // > ```go 69 | // > type TwoImplOne struct 70 | // > ``` 71 | // documentation 72 | // > ```go 73 | // > struct{} 74 | // > ``` 75 | // relationship 0.1.test `sg/testdata`/InterfaceWithSingleMethodTwoImplementers# implementation 76 | 77 | func (TwoImplOne) SingleMethodTwoImpl() float64 { return 5.0 } 78 | // ^^^^^^^^^^ reference 0.1.test `sg/testdata`/TwoImplOne# 79 | // ^^^^^^^^^^^^^^^^^^^ definition 0.1.test `sg/testdata`/TwoImplOne#SingleMethodTwoImpl(). 80 | // documentation 81 | // > ```go 82 | // > func (TwoImplOne).SingleMethodTwoImpl() float64 83 | // > ``` 84 | // relationship 0.1.test `sg/testdata`/InterfaceWithSingleMethodTwoImplementers#SingleMethodTwoImpl. implementation 85 | 86 | type TwoImplTwo struct{} 87 | // ^^^^^^^^^^ definition 0.1.test `sg/testdata`/TwoImplTwo# 88 | // documentation 89 | // > ```go 90 | // > type TwoImplTwo struct 91 | // > ``` 92 | // documentation 93 | // > ```go 94 | // > struct{} 95 | // > ``` 96 | // relationship 0.1.test `sg/testdata`/InterfaceWithSingleMethodTwoImplementers# implementation 97 | 98 | func (TwoImplTwo) SingleMethodTwoImpl() float64 { return 5.0 } 99 | // ^^^^^^^^^^ reference 0.1.test `sg/testdata`/TwoImplTwo# 100 | // ^^^^^^^^^^^^^^^^^^^ definition 0.1.test `sg/testdata`/TwoImplTwo#SingleMethodTwoImpl(). 101 | // documentation 102 | // > ```go 103 | // > func (TwoImplTwo).SingleMethodTwoImpl() float64 104 | // > ``` 105 | // relationship 0.1.test `sg/testdata`/InterfaceWithSingleMethodTwoImplementers#SingleMethodTwoImpl. implementation 106 | func (TwoImplTwo) RandomThingThatDoesntMatter() float64 { return 5.0 } 107 | // ^^^^^^^^^^ reference 0.1.test `sg/testdata`/TwoImplTwo# 108 | // ^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition 0.1.test `sg/testdata`/TwoImplTwo#RandomThingThatDoesntMatter(). 109 | // documentation 110 | // > ```go 111 | // > func (TwoImplTwo).RandomThingThatDoesntMatter() float64 112 | // > ``` 113 | 114 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/testdata/implementations_remote.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | // ^^^^^^^^ reference 0.1.test `sg/testdata`/ 3 | 4 | import "net/http" 5 | // ^^^^^^^^ reference github.com/golang/go/src go1.22 `net/http`/ 6 | 7 | type implementsWriter struct{} 8 | // ^^^^^^^^^^^^^^^^ definition 0.1.test `sg/testdata`/implementsWriter# 9 | // documentation 10 | // > ```go 11 | // > type implementsWriter struct 12 | // > ``` 13 | // documentation 14 | // > ```go 15 | // > struct{} 16 | // > ``` 17 | // relationship github.com/golang/go/src go1.22 `crypto/tls`/transcriptHash# implementation 18 | // relationship github.com/golang/go/src go1.22 `internal/bisect`/Writer# implementation 19 | // relationship github.com/golang/go/src go1.22 `net/http`/ResponseWriter# implementation 20 | // relationship github.com/golang/go/src go1.22 io/Writer# implementation 21 | 22 | func (implementsWriter) Header() http.Header { panic("Just for how") } 23 | // ^^^^^^^^^^^^^^^^ reference 0.1.test `sg/testdata`/implementsWriter# 24 | // ^^^^^^ definition 0.1.test `sg/testdata`/implementsWriter#Header(). 25 | // documentation 26 | // > ```go 27 | // > func (implementsWriter).Header() Header 28 | // > ``` 29 | // relationship github.com/golang/go/src go1.22 `net/http`/ResponseWriter#Header. implementation 30 | // ^^^^ reference github.com/golang/go/src go1.22 `net/http`/ 31 | // ^^^^^^ reference github.com/golang/go/src go1.22 `net/http`/Header# 32 | func (implementsWriter) Write([]byte) (int, error) { panic("Just for show") } 33 | // ^^^^^^^^^^^^^^^^ reference 0.1.test `sg/testdata`/implementsWriter# 34 | // ^^^^^ definition 0.1.test `sg/testdata`/implementsWriter#Write(). 35 | // documentation 36 | // > ```go 37 | // > func (implementsWriter).Write([]byte) (int, error) 38 | // > ``` 39 | // relationship github.com/golang/go/src go1.22 `crypto/tls`/transcriptHash#Write. implementation 40 | // relationship github.com/golang/go/src go1.22 `internal/bisect`/Writer#Write. implementation 41 | // relationship github.com/golang/go/src go1.22 `net/http`/ResponseWriter#Write. implementation 42 | // relationship github.com/golang/go/src go1.22 io/Writer#Write. implementation 43 | func (implementsWriter) WriteHeader(statusCode int) {} 44 | // ^^^^^^^^^^^^^^^^ reference 0.1.test `sg/testdata`/implementsWriter# 45 | // ^^^^^^^^^^^ definition 0.1.test `sg/testdata`/implementsWriter#WriteHeader(). 46 | // documentation 47 | // > ```go 48 | // > func (implementsWriter).WriteHeader(statusCode int) 49 | // > ``` 50 | // relationship github.com/golang/go/src go1.22 `net/http`/ResponseWriter#WriteHeader. implementation 51 | // ^^^^^^^^^^ definition local 0 52 | 53 | func ShowsInSignature(respWriter http.ResponseWriter) { 54 | // ^^^^^^^^^^^^^^^^ definition 0.1.test `sg/testdata`/ShowsInSignature(). 55 | // documentation 56 | // > ```go 57 | // > func ShowsInSignature(respWriter ResponseWriter) 58 | // > ``` 59 | // ^^^^^^^^^^ definition local 1 60 | // ^^^^ reference github.com/golang/go/src go1.22 `net/http`/ 61 | // ^^^^^^^^^^^^^^ reference github.com/golang/go/src go1.22 `net/http`/ResponseWriter# 62 | respWriter.WriteHeader(1) 63 | // ^^^^^^^^^^ reference local 1 64 | // ^^^^^^^^^^^ reference github.com/golang/go/src go1.22 `net/http`/ResponseWriter#WriteHeader. 65 | } 66 | 67 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/testdata/internal/secret/doc.go: -------------------------------------------------------------------------------- 1 | // secret is a package that holds secrets. 2 | package secret 3 | // ^^^^^^ definition 0.1.test `sg/testdata/internal/secret`/ 4 | // documentation 5 | // > secret is a package that holds secrets. 6 | 7 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/testdata/internal/secret/secret.go: -------------------------------------------------------------------------------- 1 | package secret 2 | // ^^^^^^ reference 0.1.test `sg/testdata/internal/secret`/ 3 | 4 | // SecretScore is like score but _secret_. 5 | const SecretScore = uint64(43) 6 | // ^^^^^^^^^^^ definition 0.1.test `sg/testdata/internal/secret`/SecretScore. 7 | // documentation 8 | // > ```go 9 | // > const SecretScore uint64 = 43 10 | // > ``` 11 | // documentation 12 | // > SecretScore is like score but _secret_. 13 | 14 | // Original doc 15 | type Burger struct { 16 | // ^^^^^^ definition 0.1.test `sg/testdata/internal/secret`/Burger# 17 | // documentation 18 | // > ```go 19 | // > type Burger struct 20 | // > ``` 21 | // documentation 22 | // > Original doc 23 | // documentation 24 | // > ```go 25 | // > struct { 26 | // > Field int 27 | // > } 28 | // > ``` 29 | Field int 30 | // ^^^^^ definition 0.1.test `sg/testdata/internal/secret`/Burger#Field. 31 | // documentation 32 | // > ```go 33 | // > struct field Field int 34 | // > ``` 35 | } 36 | 37 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/testdata/named_import.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | // ^^^^^^^^ reference 0.1.test `sg/testdata`/ 3 | 4 | import ( 5 | . "fmt" 6 | // ^^^ reference github.com/golang/go/src go1.22 fmt/ 7 | h "net/http" 8 | // ^ definition local 0 9 | // ^^^^^^^^ reference github.com/golang/go/src go1.22 `net/http`/ 10 | ) 11 | 12 | func Example() { 13 | // ^^^^^^^ definition 0.1.test `sg/testdata`/Example(). 14 | // documentation 15 | // > ```go 16 | // > func Example() 17 | // > ``` 18 | Println(h.CanonicalHeaderKey("accept-encoding")) 19 | // ^^^^^^^ reference github.com/golang/go/src go1.22 fmt/Println(). 20 | // ^ reference local 0 21 | // ^^^^^^^^^^^^^^^^^^ reference github.com/golang/go/src go1.22 `net/http`/CanonicalHeaderKey(). 22 | } 23 | 24 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/testdata/parallel.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | // ^^^^^^^^ reference 0.1.test `sg/testdata`/ 3 | 4 | import ( 5 | "context" 6 | // ^^^^^^^ reference github.com/golang/go/src go1.22 context/ 7 | "sync" 8 | // ^^^^ reference github.com/golang/go/src go1.22 sync/ 9 | ) 10 | 11 | // ParallelizableFunc is a function that can be called concurrently with other instances 12 | // of this function type. 13 | type ParallelizableFunc func(ctx context.Context) error 14 | // ^^^^^^^^^^^^^^^^^^ definition 0.1.test `sg/testdata`/ParallelizableFunc# 15 | // documentation 16 | // > ParallelizableFunc is a function that can be called concurrently with other instances 17 | // > of this function type. 18 | // documentation 19 | // > ```go 20 | // > func(ctx Context) error 21 | // > ``` 22 | // ^^^ definition local 0 23 | // ^^^^^^^ reference github.com/golang/go/src go1.22 context/ 24 | // ^^^^^^^ reference github.com/golang/go/src go1.22 context/Context# 25 | 26 | // Parallel invokes each of the given parallelizable functions in their own goroutines and 27 | // returns the first error to occur. This method will block until all goroutines have returned. 28 | func Parallel(ctx context.Context, fns ...ParallelizableFunc) error { 29 | // ^^^^^^^^ definition 0.1.test `sg/testdata`/Parallel(). 30 | // documentation 31 | // > ```go 32 | // > func Parallel(ctx Context, fns ...ParallelizableFunc) error 33 | // > ``` 34 | // documentation 35 | // > Parallel invokes each of the given parallelizable functions in their own goroutines and 36 | // > returns the first error to occur. This method will block until all goroutines have returned. 37 | // ^^^ definition local 1 38 | // ^^^^^^^ reference github.com/golang/go/src go1.22 context/ 39 | // ^^^^^^^ reference github.com/golang/go/src go1.22 context/Context# 40 | // ^^^ definition local 2 41 | // ^^^^^^^^^^^^^^^^^^ reference 0.1.test `sg/testdata`/ParallelizableFunc# 42 | var wg sync.WaitGroup 43 | // ^^ definition local 3 44 | // ^^^^ reference github.com/golang/go/src go1.22 sync/ 45 | // ^^^^^^^^^ reference github.com/golang/go/src go1.22 sync/WaitGroup# 46 | errs := make(chan error, len(fns)) 47 | // ^^^^ definition local 4 48 | // ^^^ reference local 2 49 | 50 | for _, fn := range fns { 51 | // ^^ definition local 5 52 | // ^^^ reference local 2 53 | wg.Add(1) 54 | // ^^ reference local 3 55 | // ^^^ reference github.com/golang/go/src go1.22 sync/WaitGroup#Add(). 56 | 57 | go func(fn ParallelizableFunc) { 58 | // ^^ definition local 6 59 | // ^^^^^^^^^^^^^^^^^^ reference 0.1.test `sg/testdata`/ParallelizableFunc# 60 | errs <- fn(ctx) 61 | // ^^^^ reference local 4 62 | // ^^ reference local 6 63 | // ^^^ reference local 1 64 | wg.Done() 65 | // ^^ reference local 3 66 | // ^^^^ reference github.com/golang/go/src go1.22 sync/WaitGroup#Done(). 67 | }(fn) 68 | // ^^ reference local 5 69 | } 70 | 71 | wg.Wait() 72 | // ^^ reference local 3 73 | // ^^^^ reference github.com/golang/go/src go1.22 sync/WaitGroup#Wait(). 74 | 75 | for err := range errs { 76 | // ^^^ definition local 7 77 | // ^^^^ reference local 4 78 | if err != nil { 79 | // ^^^ reference local 7 80 | return err 81 | // ^^^ reference local 7 82 | } 83 | } 84 | 85 | return nil 86 | } 87 | 88 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/testdata/typealias.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | // ^^^^^^^^ reference 0.1.test `sg/testdata`/ 3 | 4 | import ( 5 | "sg/testdata/internal/secret" 6 | // ^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference 0.1.test `sg/testdata/internal/secret`/ 7 | ) 8 | 9 | // Type aliased doc 10 | type SecretBurger = secret.Burger 11 | // ^^^^^^^^^^^^ definition 0.1.test `sg/testdata`/SecretBurger# 12 | // documentation 13 | // > ```go 14 | // > type SecretBurger = secret.Burger 15 | // > ``` 16 | // documentation 17 | // > Type aliased doc 18 | // documentation 19 | // > ```go 20 | // > struct { 21 | // > Field int 22 | // > } 23 | // > ``` 24 | // ^^^^^^ reference 0.1.test `sg/testdata/internal/secret`/ 25 | // ^^^^^^ reference 0.1.test `sg/testdata/internal/secret`/Burger# 26 | 27 | type BadBurger = struct { 28 | // ^^^^^^^^^ definition 0.1.test `sg/testdata`/BadBurger# 29 | // documentation 30 | // > ```go 31 | // > type BadBurger = struct 32 | // > ``` 33 | // documentation 34 | // > ```go 35 | // > struct { 36 | // > Field string 37 | // > } 38 | // > ``` 39 | Field string 40 | // ^^^^^ definition 0.1.test `sg/testdata`/BadBurger#Field. 41 | // documentation 42 | // > ```go 43 | // > struct field Field string 44 | // > ``` 45 | } 46 | 47 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/testdata/typeswitch.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | // ^^^^^^^^ reference 0.1.test `sg/testdata`/ 3 | 4 | func Switch(interfaceValue interface{}) bool { 5 | // ^^^^^^ definition 0.1.test `sg/testdata`/Switch(). 6 | // documentation 7 | // > ```go 8 | // > func Switch(interfaceValue interface{}) bool 9 | // > ``` 10 | // ^^^^^^^^^^^^^^ definition local 0 11 | switch concreteValue := interfaceValue.(type) { 12 | // ^^^^^^^^^^^^^ definition local 1 13 | // ^^^^^^^^^^^^^^ reference local 0 14 | case int: 15 | return concreteValue*3 > 10 16 | // ^^^^^^^^^^^^^ reference local 1 17 | // override_documentation 18 | // > ```go 19 | // > int 20 | // > ``` 21 | case bool: 22 | return !concreteValue 23 | // ^^^^^^^^^^^^^ reference local 1 24 | // override_documentation 25 | // > ```go 26 | // > bool 27 | // > ``` 28 | default: 29 | return false 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/testspecial/foo.go: -------------------------------------------------------------------------------- 1 | package testspecial 2 | // ^^^^^^^^^^^ definition 0.1.test `sg/testspecial`/ 3 | // documentation 4 | // > package testspecial 5 | 6 | func Foo() {} 7 | // ^^^ definition 0.1.test `sg/testspecial`/Foo(). 8 | // documentation 9 | // > ```go 10 | // > func Foo() 11 | // > ``` 12 | 13 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/testspecial/foo_other_test.go: -------------------------------------------------------------------------------- 1 | package testspecial_test 2 | // ^^^^^^^^^^^^^^^^ definition 0.1.test `sg/testspecial_test`/ 3 | // documentation 4 | // > package testspecial_test 5 | 6 | import ( 7 | "testing" 8 | // ^^^^^^^ reference github.com/golang/go/src go1.22 testing/ 9 | 10 | "sg/testspecial" 11 | // ^^^^^^^^^^^^^^ reference 0.1.test `sg/testspecial`/ 12 | ) 13 | 14 | func TestFoo_Blackbox(*testing.T) { testspecial.Foo() } 15 | // ^^^^^^^^^^^^^^^^ definition 0.1.test `sg/testspecial_test`/TestFoo_Blackbox(). 16 | // documentation 17 | // > ```go 18 | // > func TestFoo_Blackbox(*T) 19 | // > ``` 20 | // ^^^^^^^ reference github.com/golang/go/src go1.22 testing/ 21 | // ^ reference github.com/golang/go/src go1.22 testing/T# 22 | // ^^^^^^^^^^^ reference 0.1.test `sg/testspecial`/ 23 | // ^^^ reference 0.1.test `sg/testspecial`/Foo(). 24 | 25 | -------------------------------------------------------------------------------- /internal/testdata/snapshots/output/testspecial/foo_test.go: -------------------------------------------------------------------------------- 1 | package testspecial 2 | // ^^^^^^^^^^^ reference 0.1.test `sg/testspecial`/ 3 | 4 | func TestFoo_Whitebox() { Foo() } 5 | // ^^^^^^^^^^^^^^^^ definition 0.1.test `sg/testspecial`/TestFoo_Whitebox(). 6 | // documentation 7 | // > ```go 8 | // > func TestFoo_Whitebox() 9 | // > ``` 10 | // ^^^ reference 0.1.test `sg/testspecial`/Foo(). 11 | 12 | -------------------------------------------------------------------------------- /internal/visitors/scope.go: -------------------------------------------------------------------------------- 1 | package visitors 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/weightylarva/scip-go/internal/funk" 7 | "github.com/weightylarva/scip-go/internal/symbols" 8 | "github.com/sourcegraph/scip/bindings/go/scip" 9 | "golang.org/x/tools/go/packages" 10 | ) 11 | 12 | type Scope struct { 13 | descriptors []*scip.Descriptor 14 | } 15 | 16 | func NewScope(pkgPath string) *Scope { 17 | return &Scope{ 18 | descriptors: []*scip.Descriptor{ 19 | { 20 | Name: pkgPath, 21 | Suffix: scip.Descriptor_Namespace, 22 | }, 23 | }, 24 | } 25 | } 26 | 27 | func (s *Scope) push(name string, suffix scip.Descriptor_Suffix) { 28 | s.descriptors = append(s.descriptors, &scip.Descriptor{Name: name, Suffix: suffix}) 29 | } 30 | 31 | func (s *Scope) pop() { 32 | s.descriptors = s.descriptors[:len(s.descriptors)-1] 33 | } 34 | 35 | func (s *Scope) makeSymbol(pkg *packages.Package, name string, suffix scip.Descriptor_Suffix) string { 36 | return symbols.FromDescriptors(pkg, append(s.descriptors, &scip.Descriptor{Name: name, Suffix: suffix})...) 37 | } 38 | 39 | func (s *Scope) String() string { 40 | return strings.Join(funk.Map(s.descriptors, func(d *scip.Descriptor) string { 41 | return d.Name 42 | }), " > ") 43 | } 44 | -------------------------------------------------------------------------------- /internal/visitors/visitor_func.go: -------------------------------------------------------------------------------- 1 | package visitors 2 | 3 | import ( 4 | "go/ast" 5 | 6 | "github.com/weightylarva/scip-go/internal/document" 7 | "github.com/sourcegraph/scip/bindings/go/scip" 8 | "golang.org/x/tools/go/packages" 9 | ) 10 | 11 | var _ ast.Visitor = &funcVisitor{} 12 | 13 | type funcVisitor struct { 14 | pkg *packages.Package 15 | doc *document.Document 16 | scope *Scope 17 | } 18 | 19 | func (v funcVisitor) Visit(n ast.Node) ast.Visitor { 20 | if n == nil { 21 | return nil 22 | } 23 | 24 | switch node := n.(type) { 25 | case *ast.FuncDecl: 26 | // Receiver, if applicable 27 | if recv, has := receiverTypeName(node); has { 28 | v.scope.push(recv, scip.Descriptor_Type) 29 | } 30 | 31 | symbol := v.scope.makeSymbol(v.pkg, node.Name.Name, scip.Descriptor_Method) 32 | v.doc.SetNewSymbol(symbol, node, node.Name) 33 | 34 | // Any associated declarations should be generated with the scope of this method 35 | v.scope.push("func", scip.Descriptor_Meta) 36 | v.scope.push(node.Name.Name, scip.Descriptor_Meta) 37 | ast.Walk(v, node.Type) 38 | v.scope.pop() 39 | 40 | return nil 41 | 42 | case *ast.FuncType: 43 | // Should not need to declare any non-local definitions in the type params 44 | // if node.TypeParams != nil { 45 | // Walk(v, node.TypeParams) 46 | // } 47 | 48 | // Should not need to declare any non-local definitions in the params 49 | // if node.Params != nil { 50 | // Walk(v, node.Params) 51 | // } 52 | 53 | // Types can create new interfaces and/or types, 54 | // so we need to visit them and potentially declare new non-local symbols 55 | if node.Results != nil { 56 | ast.Walk(v, node.Results) 57 | } 58 | 59 | return nil 60 | 61 | case *ast.BlockStmt: 62 | return nil 63 | 64 | case *ast.InterfaceType: 65 | // TODO: Should handle this more elegantly? 66 | for _, field := range node.Methods.List { 67 | for _, name := range field.Names { 68 | symbol := v.scope.makeSymbol(v.pkg, name.Name, scip.Descriptor_Method) 69 | v.doc.SetNewSymbol(symbol, name, name) 70 | } 71 | } 72 | 73 | return nil 74 | 75 | default: 76 | return v 77 | } 78 | 79 | } 80 | 81 | func visitFunctionDefinition(doc *document.Document, pkg *packages.Package, node *ast.FuncDecl) { 82 | visitor := funcVisitor{ 83 | pkg: pkg, 84 | doc: doc, 85 | scope: NewScope(pkg.PkgPath), 86 | } 87 | 88 | ast.Walk(visitor, node) 89 | } 90 | 91 | func receiverTypeName(f *ast.FuncDecl) (string, bool) { 92 | recv := f.Recv 93 | if recv == nil { 94 | return "", false 95 | } 96 | 97 | if len(recv.List) > 1 { 98 | panic("I don't understand what this would look like") 99 | } else if len(recv.List) == 0 { 100 | return "", false 101 | } 102 | 103 | field := recv.List[0] 104 | if field.Type == nil { 105 | return "", false 106 | } 107 | 108 | // Dereference pointer receiver types 109 | typ := field.Type 110 | if p, _ := typ.(*ast.StarExpr); p != nil { 111 | typ = p.X 112 | } 113 | 114 | // If we have an identifier, then we have a receiver 115 | if p, _ := typ.(*ast.Ident); p != nil { 116 | return p.Name, true 117 | } 118 | 119 | return "", false 120 | } 121 | -------------------------------------------------------------------------------- /internal/visitors/visitor_type.go: -------------------------------------------------------------------------------- 1 | package visitors 2 | 3 | import ( 4 | "go/ast" 5 | 6 | "github.com/weightylarva/scip-go/internal/document" 7 | "github.com/weightylarva/scip-go/internal/symbols" 8 | "github.com/sourcegraph/scip/bindings/go/scip" 9 | "golang.org/x/tools/go/packages" 10 | ) 11 | 12 | func visitTypesInFile(doc *document.Document, pkg *packages.Package, file *ast.File) { 13 | visitor := typeVisitor{ 14 | pkg: pkg, 15 | doc: doc, 16 | scope: NewScope(pkg.PkgPath), 17 | } 18 | 19 | ast.Walk(visitor, file) 20 | } 21 | 22 | // typeVisitor collects the all the information for top-level structs 23 | // that can be imported by any other file (they do not have to be exported). 24 | // 25 | // For example, a struct `myStruct` can be imported by other files in the same 26 | // packages. So we need to make those field names global (we only have global 27 | // or file-local). 28 | type typeVisitor struct { 29 | doc *document.Document 30 | pkg *packages.Package 31 | 32 | scope *Scope 33 | curDecl *ast.GenDecl 34 | isInterface bool 35 | } 36 | 37 | func (v typeVisitor) Visit(n ast.Node) (w ast.Visitor) { 38 | if n == nil { 39 | return nil 40 | } 41 | 42 | switch node := n.(type) { 43 | case *ast.GenDecl: 44 | // Current declaration is required for some documentation parsing. 45 | // So we have to keep this here with us as we traverse more deeply 46 | v.curDecl = node 47 | 48 | if node.Doc != nil { 49 | ast.Walk(v, node.Doc) 50 | } 51 | 52 | for _, s := range node.Specs { 53 | switch spec := s.(type) { 54 | case *ast.TypeSpec: 55 | switch spec.Type.(type) { 56 | case *ast.InterfaceType: 57 | v.isInterface = true 58 | default: 59 | v.isInterface = false 60 | } 61 | } 62 | 63 | ast.Walk(v, s) 64 | } 65 | 66 | return nil 67 | 68 | case 69 | // Continue down file and decls 70 | *ast.File, 71 | 72 | // Toplevel types that are important 73 | *ast.StructType, 74 | *ast.InterfaceType, 75 | 76 | // Continue traversing subtypes 77 | *ast.FieldList, 78 | *ast.Ident: 79 | 80 | return v 81 | 82 | case *ast.TypeSpec: 83 | v.scope.push(node.Name.Name, scip.Descriptor_Type) 84 | defer func() { 85 | v.scope.pop() 86 | }() 87 | 88 | v.doc.SetNewSymbol( 89 | symbols.FromDescriptors(v.pkg, v.scope.descriptors...), 90 | v.curDecl, 91 | node.Name, 92 | ) 93 | 94 | ast.Walk(v, node.Type) 95 | case *ast.Field: 96 | // I think the only case of this is embedded fields. 97 | if len(node.Names) == 0 { 98 | // If we have an interface, these do not *declare* a new symbol, 99 | // they simply add another constraint. 100 | if v.isInterface { 101 | return v 102 | } 103 | 104 | names := getIdentOfTypeExpr(v.pkg, node.Type) 105 | for _, name := range names { 106 | embeddedSymbol := v.makeSymbol(&scip.Descriptor{ 107 | Name: name.Name, 108 | Suffix: scip.Descriptor_Term, 109 | }) 110 | 111 | // In this odd scenario, the definition is at embedded field level, 112 | // not wherever the name is. So that messes up our lookup table. 113 | v.doc.SetNewSymbolForPos(embeddedSymbol, node, name, name.Pos()) 114 | } 115 | } else { 116 | for _, name := range node.Names { 117 | v.doc.SetNewSymbol(v.makeSymbol(&scip.Descriptor{ 118 | Name: name.Name, 119 | Suffix: scip.Descriptor_Term, 120 | }), nil, name) 121 | 122 | switch typ := node.Type.(type) { 123 | case *ast.MapType: 124 | v.scope.push(name.Name, scip.Descriptor_Term) 125 | defer func() { 126 | v.scope.pop() 127 | }() 128 | 129 | ast.Walk(v, typ.Key) 130 | ast.Walk(v, typ.Value) 131 | 132 | case *ast.ArrayType: 133 | v.scope.push(name.Name, scip.Descriptor_Term) 134 | defer func() { 135 | v.scope.pop() 136 | }() 137 | 138 | ast.Walk(v, typ.Elt) 139 | 140 | case *ast.StructType, *ast.InterfaceType: 141 | // Current scope is now embedded in the anonymous struct 142 | // So we walk the rest of the type expression and save 143 | // the nested names 144 | v.scope.push(name.Name, scip.Descriptor_Term) 145 | defer func() { 146 | v.scope.pop() 147 | }() 148 | 149 | ast.Walk(v, node.Type) 150 | } 151 | } 152 | } 153 | } 154 | 155 | return nil 156 | } 157 | 158 | // Implements ast.Visitor 159 | var _ ast.Visitor = &typeVisitor{} 160 | 161 | func (s *typeVisitor) makeSymbol(descriptor *scip.Descriptor) string { 162 | return symbols.FromDescriptors(s.pkg, append(s.scope.descriptors, descriptor)...) 163 | } 164 | -------------------------------------------------------------------------------- /internal/visitors/visitor_var.go: -------------------------------------------------------------------------------- 1 | package visitors 2 | 3 | import ( 4 | "fmt" 5 | "go/ast" 6 | "go/token" 7 | 8 | "github.com/weightylarva/scip-go/internal/document" 9 | "github.com/weightylarva/scip-go/internal/handler" 10 | "github.com/weightylarva/scip-go/internal/symbols" 11 | "github.com/sourcegraph/scip/bindings/go/scip" 12 | "golang.org/x/tools/go/packages" 13 | ) 14 | 15 | func visitVarDefinition(doc *document.Document, pkg *packages.Package, decl *ast.GenDecl) { 16 | ast.Walk(&varVisitor{ 17 | doc: doc, 18 | pkg: pkg, 19 | scope: NewScope(pkg.PkgPath), 20 | }, decl) 21 | } 22 | 23 | type varVisitor struct { 24 | doc *document.Document 25 | pkg *packages.Package 26 | 27 | curDecl ast.Decl 28 | scope *Scope 29 | } 30 | 31 | var _ ast.Visitor = &varVisitor{} 32 | 33 | func (v *varVisitor) Visit(n ast.Node) (w ast.Visitor) { 34 | if n == nil { 35 | return nil 36 | } 37 | 38 | switch node := n.(type) { 39 | case *ast.GenDecl: 40 | switch node.Tok { 41 | // Only traverse vars and consts 42 | case token.VAR, token.CONST: 43 | v.curDecl = node 44 | return v 45 | default: 46 | return nil 47 | } 48 | 49 | case *ast.ValueSpec: 50 | // Iterate over names, which are the only thing that can be definitions 51 | for _, name := range node.Names { 52 | symbol := v.makeSymbol(descriptorTerm(name.Name)) 53 | v.doc.SetNewSymbol(symbol, v.curDecl, name) 54 | } 55 | 56 | if len(node.Names) > 0 { 57 | var scopeName string 58 | if len(node.Names) == 1 { 59 | scopeName = node.Names[0].Name 60 | } else { 61 | position := v.pkg.Fset.Position(node.Pos()) 62 | scopeName = fmt.Sprintf("inline-%d-%d", position.Line, position.Column) 63 | } 64 | 65 | v.scope.push(scopeName, scip.Descriptor_Meta) 66 | if node.Type != nil { 67 | switch valueType := node.Type.(type) { 68 | case *ast.FuncType: 69 | // nothing 70 | case *ast.Ident: 71 | // nothing 72 | case *ast.ChanType: 73 | // TODO: Could have chan with new struct 74 | case *ast.ArrayType: 75 | // TODO: Could have array with new struct 76 | case *ast.MapType: 77 | // TODO: could have nested struct? 78 | case *ast.StarExpr: 79 | // TODO: could be *struct? 80 | case *ast.SelectorExpr: 81 | // TODO? 82 | case *ast.IndexExpr: 83 | // TODO: Generics, possibly need to travrerse 84 | case *ast.InterfaceType: 85 | ast.Walk(v, valueType) 86 | case *ast.StructType: 87 | // panic(fmt.Sprintf("TODO: handle type %T %s", valueType, v.pkg.Fset.Position(node.Pos()))) 88 | ast.Walk(v, valueType) 89 | default: 90 | // TODO: Consider how we could emit errors for users running this, not in dev mode 91 | _ = handler.ErrOrPanic("TODO: handle type %T %s", valueType, v.pkg.Fset.Position(node.Pos())) 92 | 93 | return 94 | } 95 | } 96 | 97 | walkExprList(v, node.Values) 98 | v.scope.pop() 99 | } 100 | 101 | return nil 102 | 103 | case *ast.Field: 104 | // I think the only case of this is embedded fields. 105 | if len(node.Names) == 0 { 106 | 107 | names := getIdentOfTypeExpr(v.pkg, node.Type) 108 | for _, name := range names { 109 | embeddedSymbol := v.makeSymbol(&scip.Descriptor{ 110 | Name: name.Name, 111 | Suffix: scip.Descriptor_Term, 112 | }) 113 | 114 | // In this odd scenario, the definition is at embedded field level, 115 | // not wherever the name is. So that messes up our lookup table. 116 | v.doc.SetNewSymbolForPos(embeddedSymbol, node, name, node.Pos()) 117 | } 118 | } else { 119 | for _, name := range node.Names { 120 | v.doc.SetNewSymbol(v.makeSymbol(&scip.Descriptor{ 121 | Name: name.Name, 122 | Suffix: scip.Descriptor_Term, 123 | }), nil, name) 124 | 125 | switch typ := node.Type.(type) { 126 | case *ast.MapType: 127 | v.scope.push(name.Name, scip.Descriptor_Term) 128 | defer func() { 129 | v.scope.pop() 130 | }() 131 | 132 | ast.Walk(v, typ.Key) 133 | ast.Walk(v, typ.Value) 134 | 135 | case *ast.ArrayType: 136 | v.scope.push(name.Name, scip.Descriptor_Term) 137 | defer func() { 138 | v.scope.pop() 139 | }() 140 | 141 | ast.Walk(v, typ.Elt) 142 | 143 | case *ast.StructType, *ast.InterfaceType: 144 | // Current scope is now embedded in the anonymous struct 145 | // So we walk the rest of the type expression and save 146 | // the nested names 147 | v.scope.push(name.Name, scip.Descriptor_Term) 148 | defer func() { 149 | v.scope.pop() 150 | }() 151 | 152 | ast.Walk(v, node.Type) 153 | } 154 | } 155 | } 156 | return nil 157 | 158 | default: 159 | return v 160 | } 161 | } 162 | 163 | func (s *varVisitor) makeSymbol(descriptor *scip.Descriptor) string { 164 | return symbols.FromDescriptors(s.pkg, append(s.scope.descriptors, descriptor)...) 165 | } 166 | -------------------------------------------------------------------------------- /internal/visitors/visitors.go: -------------------------------------------------------------------------------- 1 | package visitors 2 | 3 | import ( 4 | "go/ast" 5 | "go/token" 6 | "go/types" 7 | "path/filepath" 8 | "strings" 9 | 10 | "github.com/weightylarva/scip-go/internal/document" 11 | "github.com/weightylarva/scip-go/internal/handler" 12 | "github.com/weightylarva/scip-go/internal/lookup" 13 | "github.com/sourcegraph/scip/bindings/go/scip" 14 | "golang.org/x/tools/go/packages" 15 | ) 16 | 17 | func VisitPackageSyntax( 18 | moduleRoot string, 19 | pkg *packages.Package, 20 | pathToDocuments map[string]*document.Document, 21 | globalSymbols *lookup.Global, 22 | ) { 23 | pkgSymbols := lookup.NewPackageSymbols(pkg) 24 | // Iterate over all the files, collect any global symbols 25 | for _, f := range pkg.Syntax { 26 | 27 | abs := pkg.Fset.File(f.Package).Name() 28 | relative, _ := filepath.Rel(moduleRoot, abs) 29 | 30 | doc := visitSyntax(pkg, pkgSymbols, f, relative) 31 | 32 | // Save document for pass 2 33 | pathToDocuments[abs] = doc 34 | } 35 | 36 | globalSymbols.Add(pkgSymbols) 37 | } 38 | 39 | func visitSyntax(pkg *packages.Package, pkgSymbols *lookup.Package, f *ast.File, relative string) *document.Document { 40 | doc := document.NewDocument(relative, pkg, pkgSymbols) 41 | 42 | // TODO: Maybe we should do this before? we have traverse all 43 | // the fields first before, but now I think it's fine right here 44 | // .... maybe 45 | visitTypesInFile(doc, pkg, f) 46 | 47 | for _, decl := range f.Decls { 48 | switch decl := decl.(type) { 49 | case *ast.BadDecl: 50 | continue 51 | 52 | case *ast.GenDecl: 53 | switch decl.Tok { 54 | case token.IMPORT: 55 | // These do not create global symbols 56 | continue 57 | 58 | case token.TYPE: 59 | // We do this via visitTypesInFile above 60 | 61 | case token.VAR, token.CONST: 62 | // visit var 63 | visitVarDefinition(doc, pkg, decl) 64 | 65 | default: 66 | panic("Unhandled general declaration") 67 | } 68 | 69 | case *ast.FuncDecl: 70 | visitFunctionDefinition(doc, pkg, decl) 71 | } 72 | 73 | } 74 | 75 | return doc 76 | } 77 | 78 | func walkExprList(v ast.Visitor, list []ast.Expr) { 79 | for _, x := range list { 80 | ast.Walk(v, x) 81 | } 82 | } 83 | 84 | func walkDeclList(v ast.Visitor, list []ast.Decl) { 85 | for _, x := range list { 86 | ast.Walk(v, x) 87 | } 88 | } 89 | 90 | func descriptorTerm(name string) *scip.Descriptor { 91 | return &scip.Descriptor{ 92 | Name: name, 93 | Suffix: scip.Descriptor_Term, 94 | } 95 | } 96 | 97 | func scipRange(position token.Position, obj types.Object) []int32 { 98 | var adjustment int32 = 0 99 | if pkgName, ok := obj.(*types.PkgName); ok && strings.HasPrefix(pkgName.Name(), `"`) { 100 | adjustment = 1 101 | } 102 | 103 | line := int32(position.Line - 1) 104 | column := int32(position.Column - 1) 105 | n := int32(len(obj.Name())) 106 | 107 | return []int32{line, column + adjustment, column + n - adjustment} 108 | } 109 | 110 | func getIdentOfTypeExpr(pkg *packages.Package, ty ast.Expr) []*ast.Ident { 111 | switch ty := ty.(type) { 112 | case *ast.Ident: 113 | return []*ast.Ident{ty} 114 | case *ast.SelectorExpr: 115 | return []*ast.Ident{ty.Sel} 116 | case *ast.StarExpr: 117 | return getIdentOfTypeExpr(pkg, ty.X) 118 | case *ast.IndexExpr: 119 | return getIdentOfTypeExpr(pkg, ty.X) 120 | case *ast.BinaryExpr: 121 | // As far as I can tell, binary exprs are ONLY for type constraints 122 | // and those don't really define anything on the struct. 123 | // 124 | // So far now, we'll just not return anything. 125 | // 126 | // return append(s.getIdentOfTypeExpr(ty.X), s.getIdentOfTypeExpr(ty.Y)...) 127 | return []*ast.Ident{} 128 | case *ast.UnaryExpr: 129 | return getIdentOfTypeExpr(pkg, ty.X) 130 | 131 | // TODO: This one does seem like something we should handle 132 | case *ast.IndexListExpr: 133 | return nil 134 | 135 | // TODO: Should see if any of these need better ident finders 136 | case *ast.InterfaceType: 137 | return nil 138 | case *ast.FuncType: 139 | return nil 140 | case *ast.FuncLit: 141 | return nil 142 | case *ast.MapType: 143 | return nil 144 | case *ast.ArrayType: 145 | return nil 146 | case *ast.ChanType: 147 | return nil 148 | 149 | default: 150 | _ = handler.ErrOrPanic("Unhandled named struct field: %T %+v\n%s", ty, ty, pkg.Fset.Position(ty.Pos())) 151 | return nil 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /scripts/dockerfile_checks.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | fromGolangLines="$(grep 'FROM golang' Dockerfile | wc -l)" 4 | if [[ "$fromGolangLines" -ne 2 ]]; then 5 | echo "Expected exactly 2 FROM lines in Dockerfile" 6 | exit 1 7 | fi 8 | 9 | uniqueGolangImages="$(grep 'FROM golang' Dockerfile | cut -d " " -f 2 | uniq | wc -l)" 10 | if [[ "$uniqueGolangImages" -ne 1 ]]; then 11 | echo "Expected same image to be repeated in Dockerfile" 12 | exit 1 13 | fi 14 | 15 | golangTag="$(grep 'FROM golang' Dockerfile | head -n 1 | cut -d " " -f 2 | cut -d "@" -f 1)" 16 | golangSha="$(grep 'FROM golang' Dockerfile | head -n 1 | cut -d " " -f 2 | cut -d "@" -f 2)" 17 | digestLine="$(docker buildx imagetools inspect "$golangTag" | grep -E "^Digest:")" 18 | if [[ "$digestLine" =~ *"golangSha"* ]]; then 19 | echo "SHA for $golangTag image ($golangSha) does not match $digestLine" 20 | exit 1 21 | fi 22 | -------------------------------------------------------------------------------- /scripts/gen_std_lib.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | cat > ./internal/loader/stdlib.go << EOT 5 | // THIS FILE IS GENERATED. SEE ./scripts/gen_std_lib.sh 6 | EOT 7 | 8 | echo "// Generated by: $(go version)" >> ./internal/loader/stdlib.go 9 | 10 | cat >> ./internal/loader/stdlib.go << EOT 11 | package loader 12 | 13 | var contained = struct{}{} 14 | 15 | // This list is calculated from "go list std". 16 | var stdPackages = map[string]struct{}{ 17 | EOT 18 | 19 | # Runs golist, replaces all the subsequent sub packages with nothing 20 | # and the sorts, and uniqs them, to then print them out into strings 21 | # in a map 22 | 23 | go list std \ 24 | | sed 's:/.*$::' \ 25 | | sort \ 26 | | uniq \ 27 | | awk '{ print "\""$0"\": contained,"}' >> ./internal/loader/stdlib.go 28 | 29 | echo "}" >> ./internal/loader/stdlib.go 30 | 31 | go fmt ./internal/loader/stdlib.go 32 | -------------------------------------------------------------------------------- /scripts/sourcegraph_qa.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Define default output directory 4 | output_dir="scratch" 5 | dev_flag="" 6 | 7 | # Parse command line arguments 8 | while [[ $# -gt 0 ]]; do 9 | key="$1" 10 | case $key in 11 | -o|--output) 12 | output_dir="$2" 13 | shift 2 14 | ;; 15 | --dev) 16 | dev_flag="--dev" 17 | shift 18 | ;; 19 | *) 20 | echo "Unknown option: $1" 21 | exit 1 22 | ;; 23 | esac 24 | done 25 | 26 | # 27 | pids=() 28 | 29 | # Define a function to download and run command on each repository 30 | function download_and_run_command { 31 | repo=$1 32 | if [ ! -d "$output_dir/$(basename "$repo")" ]; then 33 | git clone "https://$repo.git" "$output_dir/$(basename "$repo")" & 34 | pid=$! 35 | wait $pid 36 | else 37 | echo "already cloned $repo" 38 | fi 39 | cd "$output_dir/$(basename "$repo")" 40 | echo "running : $repo" 41 | output=$(../../scip-go $dev_flag 2>&1 &) 42 | pid=$! 43 | pids+=($pid) 44 | 45 | if [ $? -eq 0 ]; then 46 | echo "completed : $repo" 47 | else 48 | echo "failed : $repo" 49 | echo "===========================================" 50 | echo "$output" 51 | echo "===========================================" 52 | fi 53 | cd ../.. 54 | } 55 | 56 | # Create output directory if it doesn't exist 57 | if [ ! -d "$output_dir" ]; then 58 | mkdir -p "$output_dir" 59 | fi 60 | 61 | # Define an array of repositories to download 62 | repos=( 63 | "github.com/weightylarva/scip-go" 64 | "github.com/sourcegraph-testing/etcd" 65 | "github.com/sourcegraph-testing/tidb" 66 | "github.com/sourcegraph-testing/titan" 67 | "github.com/sourcegraph-testing/zap" 68 | "github.com/sourcegraph-testing/nacelle" 69 | "github.com/sourcegraph-testing/nacelle-config" 70 | "github.com/sourcegraph-testing/nacelle-service" 71 | "github.com/sourcegraph/code-intel-extensions" 72 | ) 73 | 74 | # Download and run command on each repository in parallel 75 | for repo in "${repos[@]}"; do 76 | download_and_run_command "$repo" & 77 | done 78 | 79 | # Wait for all commands to finish 80 | while true; do 81 | echo "checking jobs..." 82 | 83 | for pid in "${pids[@]}"; do 84 | if jobs -l | grep -q $pid; then 85 | echo "stil waiting for $pid" 86 | fi 87 | done 88 | 89 | sleep 1; 90 | done 91 | --------------------------------------------------------------------------------