Skip to content

x/tools/gopls: unimported completion drops most types from workspace packages #81369

Description

@efrem0ff

gopls version

golang.org/x/tools/gopls v0.23.0
go version go1.27.1 darwin/arm64

What did you do?

Two packages in one module, where b does not import a.

a/a.go:

package a

type Alpha [16]byte
type Beta interface{}
type Gamma struct{}
type Zeta func(int)
func New() Alpha { return Alpha{} }
const Delta = 1
var Epsilon = 2

b/b.go:

package b

func f() {
	a.
}

Request textDocument/completion at the position after "a.".

What did you expect to see?

All seven exported symbols offered as unimported completions, each with an
auto-import edit. The doc comment at the top of
gopls/internal/golang/completion/unimported.go says as much:

A 'suitable completion' is an exported symbol (so a type, const, var,
or func) from package foo [...]

What did you see instead?

Five of the seven are offered. Driving gopls directly over stdio and printing
the label, detail and kind of every item returned:

gopls: golang.org/x/tools/gopls v0.23.0
items returned: 5

symbol     offered   detail                          kind
---------- --------- ------------------------------- ---------
Alpha      no
Beta       no
Gamma      yes       var (from "example.com/m/a")    Variable
Zeta       yes       func (from "example.com/m/a")   Function
New        yes       func (from "example.com/m/a")   Function
Delta      yes       const (from "example.com/m/a")  Constant
Epsilon    yes       var (from "example.com/m/a")    Variable

Alpha and Beta are missing. Gamma is a type but is labelled "var" and sent as
VariableCompletion. Zeta is a type but is labelled "func". Every item that is
offered does carry a correct auto-import edit.

Note also that no type is ever sent with a type-like completion kind, so the
editor draws a variable icon beside an item whose detail text reads "type".
The icon changes once the import is added and the symbol starts coming from
the normal completion path, which uses ClassCompletion or
InterfaceCompletion.

Cause

pkgIDmatches in unimported.go handles only the Function, Variable, Struct and
Constant symbol kinds. cache/symbols gives a type declaration the Interface
kind for an interface, Struct for a struct, Function for a named func type,
and Class for anything else. Interface and Class have no case and so hit
"default: continue"; Struct shares a case with Variable and so is labelled
"var".

This is the workspace path only. stdlibMatches and modcacheMatches already
have a Type case producing "type (from ...)", so standard library and module
cache types are fine and only the user's own packages break.

I have a fix ready and will send it as a PR.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    ToolsThis label describes issues relating to any tools in the x/tools repository.goplsIssues related to the Go language server, gopls.

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions