blob: 497b973070399545481b7b8fa7c5b4e7065abf0d [file] [log] [blame]
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package codelens
import (
"runtime"
"strings"
"testing"
"golang.org/x/tools/internal/testenv"
"golang.org/x/tools/gopls/internal/lsp/command"
"golang.org/x/tools/gopls/internal/lsp/fake"
"golang.org/x/tools/gopls/internal/lsp/protocol"
. "golang.org/x/tools/gopls/internal/lsp/regtest"
"golang.org/x/tools/internal/bug"
)
func TestGCDetails_Toggle(t *testing.T) {
testenv.NeedsGo1Point(t, 15)
if runtime.GOOS == "android" {
t.Skipf("the gc details code lens doesn't work on Android")
}
const mod = `
-- go.mod --
module mod.com
go 1.15
-- main.go --
package main
import "fmt"
func main() {
fmt.Println(42)
}
`
WithOptions(
Settings{
"codelenses": map[string]bool{
"gc_details": true,
},
},
).Run(t, mod, func(t *testing.T, env *Env) {
env.OpenFile("main.go")
env.ExecuteCodeLensCommand("main.go", command.GCDetails, nil)
d := &protocol.PublishDiagnosticsParams{}
env.Await(
OnceMet(
DiagnosticAt("main.go", 5, 13),
ReadDiagnostics("main.go", d),
),
)
// Confirm that the diagnostics come from the gc details code lens.
var found bool
for _, d := range d.Diagnostics {
if d.Severity != protocol.SeverityInformation {
t.Fatalf("unexpected diagnostic severity %v, wanted Information", d.Severity)
}
if strings.Contains(d.Message, "42 escapes") {
found = true
}
}
if !found {
t.Fatalf(`expected to find diagnostic with message "escape(42 escapes to heap)", found none`)
}
// Editing a buffer should cause gc_details diagnostics to disappear, since
// they only apply to saved buffers.
env.EditBuffer("main.go", fake.NewEdit(0, 0, 0, 0, "\n\n"))
env.Await(EmptyDiagnostics("main.go"))
// Saving a buffer should re-format back to the original state, and
// re-enable the gc_details diagnostics.
env.SaveBuffer("main.go")
env.Await(DiagnosticAt("main.go", 5, 13))
// Toggle the GC details code lens again so now it should be off.
env.ExecuteCodeLensCommand("main.go", command.GCDetails, nil)
env.Await(
EmptyDiagnostics("main.go"),
)
})
}
// Test for the crasher in golang/go#54199
func TestGCDetails_NewFile(t *testing.T) {
bug.PanicOnBugs = false
// It appears that older Go versions don't even see p.go from the initial
// workspace load.
testenv.NeedsGo1Point(t, 15)
const src = `
-- go.mod --
module mod.test
go 1.12
`
WithOptions(
Settings{
"codelenses": map[string]bool{
"gc_details": true,
},
},
).Run(t, src, func(t *testing.T, env *Env) {
env.CreateBuffer("p_test.go", "")
const gcDetailsCommand = "gopls." + string(command.GCDetails)
hasGCDetails := func() bool {
lenses := env.CodeLens("p_test.go") // should not crash
for _, lens := range lenses {
if lens.Command.Command == gcDetailsCommand {
return true
}
}
return false
}
// With an empty file, we shouldn't get the gc_details codelens because
// there is nowhere to position it (it needs a package name).
if hasGCDetails() {
t.Errorf("got the gc_details codelens for an empty file")
}
// Edit to provide a package name.
env.EditBuffer("p_test.go", fake.NewEdit(0, 0, 0, 0, "package p"))
// Now we should get the gc_details codelens.
if !hasGCDetails() {
t.Errorf("didn't get the gc_details codelens for a valid non-empty Go file")
}
})
}