Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/tools/gopls: callHierarchy/incomingCalls for a top-level function alias returns package declaration #49124

Closed
andrejtokarcik opened this issue Oct 23, 2021 · 2 comments
Labels
FrozenDueToAge gopls Issues related to the Go language server, gopls. NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. Tools This label describes issues relating to any tools in the x/tools repository.
Milestone

Comments

@andrejtokarcik
Copy link

andrejtokarcik commented Oct 23, 2021

What version of Go are you using (go version)?

$ gopls version
golang.org/x/tools/gopls v0.7.3
    golang.org/x/tools/gopls@v0.7.3 h1:Lru57ht8vtDMouRskFC085VAjBAZRAISd/lwvwOOV0Q=
$ go version  # should be irrelevant?
go version go1.16.2 linux/amd64

Does this issue reproduce with the latest release?

Yes, with the latest release of gopls, including the current tools master golang/tools@316ba0b.

What operating system and processor architecture are you using (go env)?

go env Output (should be irrelevant?)
$ go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/andrej/.cache/go-build"
GOENV="/home/andrej/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/andrej/.go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/andrej/.go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/andrej/.go1.16.2"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/andrej/.go1.16.2/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.16.2"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build3160952985=/tmp/go-build -gno-record-gcc-switches"

What did you do?

Create example.go:

package p

func f() {}

var alias = f

func g() {
	alias()
}

Run gopls, initialize an LSP exchange and fetch the incoming calls for the function f, e.g.:

// First prepare the call hierarchy:
{
    "method": "textDocument/prepareCallHierarchy",
    "params": {
        "textDocument": {
            "uri": "file:///home/andrej/gopls-panic/example.go"
        },
        "position": {
            "character": 5,
            "line": 2
        }
    },
    "jsonrpc": "2.0",
    "id": 1
}
// Handle the received call hierarchy items and send:
{
    "method": "callHierarchy/incomingCalls",
    "params": {
        "item": {
            "name": "f",
            "range": {
                "end": {
                    "character": 6,
                    "line": 2
                },
                "start": {
                    "character": 5,
                    "line": 2
                }
            },
            "selectionRange": {
                "end": {
                    "character": 6,
                    "line": 2
                },
                "start": {
                    "character": 5,
                    "line": 2
                }
            },
            "kind": 12,
            "uri": "file:///home/andrej/gopls-panic/example.go",
            "detail": "command-line-arguments:file=/home/andrej/gopls-panic/example.go ⢠example.go"
        }
    },
    "jsonrpc": "2.0",
    "id": 2
}

What did you expect to see?

Either return a reference to alias as one of the incoming calls of f (i.e. as though alias was a caller of f),
or resolve the indirection and include the incoming calls of alias (i.e. g in example.go) among the incoming calls of f.

What did you see instead?

The returned incoming calls consist of just a reference to the name in the package declaration (p in example.go).

The response for the above example request is:

{
    "result": [
        {
            "from": {
                "name": "p",
                "range": {
                    "end": {
                        "character": 9,
                        "line": 0
                    },
                    "start": {
                        "character": 8,
                        "line": 0
                    }
                },
                "selectionRange": {
                    "end": {
                        "character": 9,
                        "line": 0
                    },
                    "start": {
                        "character": 8,
                        "line": 0
                    }
                },
                "kind": 4,
                "uri": "file:///home/andrej/gopls-panic/example.go",
                "detail": "command-line-arguments:file=/home/andrej/gopls-panic/example.go ⢠example.go"
            },
            "fromRanges": [
                {
                    "end": {
                        "character": 13,
                        "line": 4
                    },
                    "start": {
                        "character": 12,
                        "line": 4
                    }
                }
            ]
        }
    ],
    "jsonrpc": "2.0",
    "id": 2
}
@gopherbot gopherbot added Tools This label describes issues relating to any tools in the x/tools repository. gopls Issues related to the Go language server, gopls. labels Oct 23, 2021
@gopherbot gopherbot added this to the Unreleased milestone Oct 23, 2021
@andrejtokarcik andrejtokarcik changed the title x/tools/gopls: callHierarchy/incomingCalls for a top-level var func returns package declaration x/tools/gopls: callHierarchy/incomingCalls for a top-level function alias returns package declaration Oct 23, 2021
@findleyr findleyr added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Oct 26, 2021
@findleyr
Copy link
Contributor

I don't think this is feasible to do. In your example, alias is not really an alias. Rather, it is a variable that holds function values. Figuring out which values a variable assumes is a Hard Problem. Consider the following more complicated example:

package p

import "time"

func f() {}

var alias = f

func init() {
   now := time.Now()
   if time.Since(now) > time.Millisecond {
     alias = func() {}
   }
}

func g() {
	alias()
}

Closing as infeasible. Please re-open if you disagree.

@andrejtokarcik
Copy link
Author

andrejtokarcik commented Oct 30, 2021

@findleyr Thanks for your reply, I don't seem to be able to reopen the issue though.

I understand your argument to rule out only my latter suggestion:

resolve the indirection and include the incoming calls of alias (i.e. g in example.go) among the incoming calls of f.

However, I'd still consider it feasible to go with my first suggestion and return a reference to alias (with SymbolKind = Variable) -- leaving it to the client/user to determine which incoming calls of alias can be false positives in the sense of not being transitive callers of f.

Finally, resolving this issue need not be restricted to my suggested solutions. As I see it, it's rather confusing to return a SymbolKind = Package as a CallHierarchyIncomingCall result in its own right so some fix would still be desired, e.g. entirely omitting any alias related result.

@golang golang locked and limited conversation to collaborators Oct 30, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge gopls Issues related to the Go language server, gopls. NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. Tools This label describes issues relating to any tools in the x/tools repository.
Projects
None yet
Development

No branches or pull requests

3 participants