golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.31k stars 17.58k forks source link

x/tools/gopls: fuzzy completion does not return result when expected #38380

Open myitcv opened 4 years ago

myitcv commented 4 years ago

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

$ go version
go version devel +801cd7c84d Thu Apr 2 09:00:44 2020 +0000 linux/amd64
$ go list -m golang.org/x/tools
golang.org/x/tools v0.0.0-20200408132156-9ee5ef7a2c0d => github.com/myitcvforks/tools v0.0.0-20200408225201-7e808beafd9f
$ go list -m golang.org/x/tools/gopls
golang.org/x/tools/gopls v0.0.0-20200408132156-9ee5ef7a2c0d => github.com/myitcvforks/tools/gopls v0.0.0-20200408225201-7e808beafd9f

Does this issue reproduce with the latest release?

Yes

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

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/myitcv/.cache/go-build"
GOENV="/home/myitcv/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/myitcv/gostuff"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/myitcv/gos"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/myitcv/gos/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/myitcv/.vim/plugged/govim/go.mod"
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-build227804233=/tmp/go-build -gno-record-gcc-switches"

What did you do?

-- go.mod --
module github.com/myitcv/playground

go 1.12
-- main.go --
package main

import (
    "fmt"
)

func main() {
    fmt.Prnf
}

What did you expect to see?

Triggering completion at the end of fmt.Prnf to return a single result, fmt.Printf

What did you see instead?

Triggering completion at the end of fmt.Prnf did not return any results.

See the following gopls log: bad.log


cc @stamblerre @muirdm

FYI @leitzler

muirdm commented 4 years ago

This is due to how the fuzzy scoring works. Non-initial, non-connected letters ("n" and "f" in "Prnf") get a big penalty. In your example, the penalized "n" and "f" outweigh the "Pr" causing the candidate not to match. Normally the user is not filtering using in-between letters.

"Printf" in particular is unlucky since "f" represents another word "Formatted", but "f" is lowercase so the fuzzy matcher doesn't know it is an important letter the user might want to use to filter results. If it was named "PrintF", for example, then it would work better.

myitcv commented 4 years ago

This is due to how the fuzzy scoring works.

Can you provide a bit of background on the thought process? Because it's somewhat strange (to me at least) that this doesn't match at all: a lower score, maybe, but no match?

My perspective, FWIW, is shaped by other fuzzy finders, like fzf

muirdm commented 4 years ago

Unfortunately I don't have any more background because I didn't write the gopls fuzzy matcher.

This is the check that counts a match with two short, non-initial matches as poor.

stamblerre commented 4 years ago

Our fuzzy matcher is adapted from a library used internally at Google, and it handles multiple languages, which may account for some of the cases that don't work as expected for Go. I don't think we will prioritize significant modifications / improvements to this library in the near future, so if anyone has a suggestion for an alternative well-supported fuzzy matching package, we can use that (much like we did for go-diff). Otherwise, we can continue to use this package with small bug fixes as needed, until we have time to prioritize this.