internal/lsp: refactor error handling code in type-checking
This change adds a source.Error type which is used to collect the error
information that comes out of the loading, parsing, and type checking
stages. We also add specific sources per-error, rather than having them
all be labeled as "LSP".
This change will enable follow-ups that do a better job of extracting
error ranges.
Change-Id: I3fbb5e42d66aa2c5bb1b2f41d1eadfc45f3a749b
Reviewed-on: https://go-review.googlesource.com/c/tools/+/202298
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
diff --git a/internal/lsp/cache/check.go b/internal/lsp/cache/check.go
index 804c3fa..049215c 100644
--- a/internal/lsp/cache/check.go
+++ b/internal/lsp/cache/check.go
@@ -9,7 +9,6 @@
"context"
"fmt"
"go/ast"
- "go/scanner"
"go/types"
"sort"
"sync"
@@ -265,6 +264,11 @@
ctx, done := trace.StartSpan(ctx, "cache.importer.typeCheck", telemetry.Package.Of(cph.m.id))
defer done()
+ var rawErrors []error
+ for _, err := range cph.m.errors {
+ rawErrors = append(rawErrors, err)
+ }
+
pkg := &pkg{
snapshot: imp.snapshot,
id: cph.m.id,
@@ -282,11 +286,6 @@
Scopes: make(map[ast.Node]*types.Scope),
},
}
- // If the package comes back with errors from `go list`,
- // don't bother type-checking it.
- for _, err := range cph.m.errors {
- pkg.errors = append(cph.m.errors, err)
- }
var (
files = make([]*ast.File, len(pkg.files))
parseErrors = make([]error, len(pkg.files))
@@ -302,9 +301,9 @@
}
wg.Wait()
- for _, err := range parseErrors {
- if err != nil {
- imp.snapshot.view.session.cache.appendPkgError(pkg, err)
+ for _, e := range parseErrors {
+ if e != nil {
+ rawErrors = append(rawErrors, e)
}
}
@@ -318,7 +317,7 @@
files = files[:i]
// Use the default type information for the unsafe package.
- if cph.m.pkgPath == "unsafe" {
+ if pkg.pkgPath == "unsafe" {
pkg.types = types.Unsafe
} else if len(files) == 0 { // not the unsafe package, no parsed files
return nil, errors.Errorf("no parsed files for package %s", pkg.pkgPath)
@@ -327,8 +326,8 @@
}
cfg := &types.Config{
- Error: func(err error) {
- imp.snapshot.view.session.cache.appendPkgError(pkg, err)
+ Error: func(e error) {
+ rawErrors = append(rawErrors, e)
},
Importer: imp.depImporter(ctx, cph, pkg),
}
@@ -337,6 +336,14 @@
// Type checking errors are handled via the config, so ignore them here.
_ = check.Files(files)
+ for _, e := range rawErrors {
+ srcErr, err := sourceError(ctx, imp.snapshot.view, pkg, e)
+ if err != nil {
+ return nil, err
+ }
+ pkg.errors = append(pkg.errors, *srcErr)
+ }
+
return pkg, nil
}
@@ -356,34 +363,3 @@
ctx: ctx,
}
}
-
-func (c *cache) appendPkgError(pkg *pkg, err error) {
- if err == nil {
- return
- }
- var errs []packages.Error
- switch err := err.(type) {
- case *scanner.Error:
- errs = append(errs, packages.Error{
- Pos: err.Pos.String(),
- Msg: err.Msg,
- Kind: packages.ParseError,
- })
- case scanner.ErrorList:
- // The first parser error is likely the root cause of the problem.
- if err.Len() > 0 {
- errs = append(errs, packages.Error{
- Pos: err[0].Pos.String(),
- Msg: err[0].Msg,
- Kind: packages.ParseError,
- })
- }
- case types.Error:
- errs = append(errs, packages.Error{
- Pos: c.FileSet().Position(err.Pos).String(),
- Msg: err.Msg,
- Kind: packages.TypeError,
- })
- }
- pkg.errors = append(pkg.errors, errs...)
-}
diff --git a/internal/lsp/source/diagnostics_test.go b/internal/lsp/cache/error_test.go
similarity index 95%
rename from internal/lsp/source/diagnostics_test.go
rename to internal/lsp/cache/error_test.go
index 12c3a57..d361e03 100644
--- a/internal/lsp/source/diagnostics_test.go
+++ b/internal/lsp/cache/error_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package source
+package cache
import (
"strings"
@@ -28,7 +28,7 @@
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- spn := parseDiagnosticMessage(tt.in)
+ spn := parseGoListError(tt.in)
fn := spn.URI().Filename()
if !strings.HasSuffix(fn, tt.expectedFileName) {
diff --git a/internal/lsp/cache/errors.go b/internal/lsp/cache/errors.go
new file mode 100644
index 0000000..c8238a8
--- /dev/null
+++ b/internal/lsp/cache/errors.go
@@ -0,0 +1,103 @@
+package cache
+
+import (
+ "bytes"
+ "context"
+ "go/scanner"
+ "go/types"
+ "strings"
+
+ "golang.org/x/tools/go/packages"
+ "golang.org/x/tools/internal/lsp/protocol"
+ "golang.org/x/tools/internal/lsp/source"
+ "golang.org/x/tools/internal/span"
+)
+
+func sourceError(ctx context.Context, view *view, pkg *pkg, e error) (*source.Error, error) {
+ var (
+ spn span.Span
+ msg string
+ kind packages.ErrorKind
+ )
+ switch e := e.(type) {
+ case packages.Error:
+ if e.Pos == "" {
+ spn = parseGoListError(e.Msg)
+ } else {
+ spn = span.Parse(e.Pos)
+ }
+ msg = e.Msg
+ kind = e.Kind
+ case *scanner.Error:
+ msg = e.Msg
+ kind = packages.ParseError
+ spn = span.Parse(e.Pos.String())
+ case scanner.ErrorList:
+ // The first parser error is likely the root cause of the problem.
+ if e.Len() > 0 {
+ spn = span.Parse(e[0].Pos.String())
+ msg = e[0].Msg
+ kind = packages.ParseError
+ }
+ case types.Error:
+ spn = span.Parse(view.session.cache.fset.Position(e.Pos).String())
+ msg = e.Msg
+ kind = packages.TypeError
+ }
+ rng, err := spanToRange(ctx, pkg, spn, kind == packages.TypeError)
+ if err != nil {
+ return nil, err
+ }
+ return &source.Error{
+ URI: spn.URI(),
+ Range: rng,
+ Msg: msg,
+ Kind: kind,
+ }, nil
+}
+
+// spanToRange converts a span.Span to a protocol.Range,
+// assuming that the span belongs to the package whose diagnostics are being computed.
+func spanToRange(ctx context.Context, pkg *pkg, spn span.Span, isTypeError bool) (protocol.Range, error) {
+ ph, err := pkg.File(spn.URI())
+ if err != nil {
+ return protocol.Range{}, err
+ }
+ _, m, _, err := ph.Cached(ctx)
+ if err != nil {
+ return protocol.Range{}, err
+ }
+ data, _, err := ph.File().Read(ctx)
+ if err != nil {
+ return protocol.Range{}, err
+ }
+ if spn.IsPoint() && isTypeError {
+ if s, err := spn.WithOffset(m.Converter); err == nil {
+ start := s.Start()
+ offset := start.Offset()
+ if offset < len(data) {
+ if width := bytes.IndexAny(data[offset:], " \n,():;[]"); width > 0 {
+ spn = span.New(spn.URI(), start, span.NewPoint(start.Line(), start.Column()+width, offset+width))
+ }
+ }
+ }
+ }
+ return m.Range(spn)
+}
+
+// parseGoListError attempts to parse a standard `go list` error message
+// by stripping off the trailing error message.
+//
+// It works only on errors whose message is prefixed by colon,
+// followed by a space (": "). For example:
+//
+// attributes.go:13:1: expected 'package', found 'type'
+//
+func parseGoListError(input string) span.Span {
+ input = strings.TrimSpace(input)
+ msgIndex := strings.Index(input, ": ")
+ if msgIndex < 0 {
+ return span.Parse(input)
+ }
+ return span.Parse(input[:msgIndex])
+}
diff --git a/internal/lsp/cache/pkg.go b/internal/lsp/cache/pkg.go
index e967c41..08aeb62 100644
--- a/internal/lsp/cache/pkg.go
+++ b/internal/lsp/cache/pkg.go
@@ -11,7 +11,6 @@
"sync"
"golang.org/x/tools/go/analysis"
- "golang.org/x/tools/go/packages"
"golang.org/x/tools/internal/lsp/protocol"
"golang.org/x/tools/internal/lsp/source"
"golang.org/x/tools/internal/span"
@@ -28,7 +27,7 @@
mode source.ParseMode
files []source.ParseGoHandle
- errors []packages.Error
+ errors []source.Error
imports map[packagePath]*pkg
types *types.Package
typesInfo *types.Info
@@ -80,7 +79,7 @@
return syntax
}
-func (p *pkg) GetErrors() []packages.Error {
+func (p *pkg) GetErrors() []source.Error {
return p.errors
}
diff --git a/internal/lsp/source/diagnostics.go b/internal/lsp/source/diagnostics.go
index 969594a..44e99c4 100644
--- a/internal/lsp/source/diagnostics.go
+++ b/internal/lsp/source/diagnostics.go
@@ -5,10 +5,8 @@
package source
import (
- "bytes"
"context"
"fmt"
- "strings"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/packages"
@@ -76,7 +74,7 @@
if err.Kind != packages.ListError {
continue
}
- clearReports(view, reports, packagesErrorSpan(err).URI())
+ clearReports(view, reports, err.URI)
}
// Run diagnostics for the package that this URI belongs to.
@@ -111,11 +109,10 @@
diagSets := make(map[span.URI]*diagnosticSet)
for _, err := range pkg.GetErrors() {
- spn := packagesErrorSpan(err)
diag := &Diagnostic{
- URI: spn.URI(),
+ URI: err.URI,
Message: err.Msg,
- Source: "LSP",
+ Range: err.Range,
Severity: protocol.SeverityError,
}
set, ok := diagSets[diag.URI]
@@ -126,17 +123,14 @@
switch err.Kind {
case packages.ParseError:
set.parseErrors = append(set.parseErrors, diag)
+ diag.Source = "syntax"
case packages.TypeError:
set.typeErrors = append(set.typeErrors, diag)
+ diag.Source = "compiler"
default:
set.listErrors = append(set.listErrors, diag)
+ diag.Source = "go list"
}
- rng, err := spanToRange(ctx, view, pkg, spn, err.Kind == packages.TypeError)
- if err != nil {
- log.Error(ctx, "failed to convert span to range", err)
- continue
- }
- diag.Range = rng
}
var nonEmptyDiagnostics bool // track if we actually send non-empty diagnostics
for uri, set := range diagSets {
@@ -159,35 +153,6 @@
return nonEmptyDiagnostics
}
-// spanToRange converts a span.Span to a protocol.Range,
-// assuming that the span belongs to the package whose diagnostics are being computed.
-func spanToRange(ctx context.Context, view View, pkg Package, spn span.Span, isTypeError bool) (protocol.Range, error) {
- ph, err := pkg.File(spn.URI())
- if err != nil {
- return protocol.Range{}, err
- }
- _, m, _, err := ph.Cached(ctx)
- if err != nil {
- return protocol.Range{}, err
- }
- data, _, err := ph.File().Read(ctx)
- if err != nil {
- return protocol.Range{}, err
- }
- // Try to get a range for the diagnostic.
- // TODO: Don't just limit ranges to type errors.
- if spn.IsPoint() && isTypeError {
- if s, err := spn.WithOffset(m.Converter); err == nil {
- start := s.Start()
- offset := start.Offset()
- if width := bytes.IndexAny(data[offset:], " \n,():;[]"); width > 0 {
- spn = span.New(spn.URI(), start, span.NewPoint(start.Line(), start.Column()+width, offset+width))
- }
- }
- }
- return m.Range(spn)
-}
-
func analyses(ctx context.Context, snapshot Snapshot, cph CheckPackageHandle, disabledAnalyses map[string]struct{}, reports map[span.URI][]Diagnostic) error {
// Type checking and parsing succeeded. Run analyses.
if err := runAnalyses(ctx, snapshot, cph, disabledAnalyses, func(diags []*analysis.Diagnostic, a *analysis.Analyzer) error {
@@ -206,10 +171,8 @@
}
func toDiagnostic(ctx context.Context, view View, diag *analysis.Diagnostic, category string) (Diagnostic, error) {
- r := span.NewRange(view.Session().Cache().FileSet(), diag.Pos, diag.End)
- spn, err := r.Span()
+ spn, err := span.NewRange(view.Session().Cache().FileSet(), diag.Pos, diag.End).Span()
if err != nil {
- // The diagnostic has an invalid position, so we don't have a valid span.
return Diagnostic{}, err
}
f, err := view.GetFile(ctx, spn.URI())
@@ -230,7 +193,15 @@
if err != nil {
return Diagnostic{}, err
}
- rng, err := spanToRange(ctx, view, pkg, spn, false)
+ ph, err := pkg.File(spn.URI())
+ if err != nil {
+ return Diagnostic{}, err
+ }
+ _, m, _, err := ph.Cached(ctx)
+ if err != nil {
+ return Diagnostic{}, err
+ }
+ rng, err := m.Range(spn)
if err != nil {
return Diagnostic{}, err
}
@@ -275,30 +246,6 @@
}
}
-func packagesErrorSpan(err packages.Error) span.Span {
- if err.Pos == "" {
- return parseDiagnosticMessage(err.Msg)
- }
- return span.Parse(err.Pos)
-}
-
-// parseDiagnosticMessage attempts to parse a standard `go list` error message
-// by stripping off the trailing error message.
-//
-// It works only on errors whose message is prefixed by colon,
-// followed by a space (": "). For example:
-//
-// attributes.go:13:1: expected 'package', found 'type'
-//
-func parseDiagnosticMessage(input string) span.Span {
- input = strings.TrimSpace(input)
- msgIndex := strings.Index(input, ": ")
- if msgIndex < 0 {
- return span.Parse(input)
- }
- return span.Parse(input[:msgIndex])
-}
-
func singleDiagnostic(uri span.URI, format string, a ...interface{}) map[span.URI][]Diagnostic {
return map[span.URI][]Diagnostic{
uri: []Diagnostic{{
diff --git a/internal/lsp/source/format.go b/internal/lsp/source/format.go
index 46f2ee2..eb14f9a 100644
--- a/internal/lsp/source/format.go
+++ b/internal/lsp/source/format.go
@@ -49,7 +49,7 @@
if err != nil {
return nil, err
}
- if hasListErrors(pkg.GetErrors()) || hasParseErrors(pkg, f.URI()) {
+ if hasListErrors(pkg) || hasParseErrors(pkg, f.URI()) {
// Even if this package has list or parse errors, this file may not
// have any parse errors and can still be formatted. Using format.Node
// on an ast with errors may result in code being added or removed.
@@ -102,7 +102,7 @@
if err != nil {
return nil, err
}
- if hasListErrors(pkg.GetErrors()) {
+ if hasListErrors(pkg) {
return nil, errors.Errorf("%s has list errors, not running goimports", f.URI())
}
ph, err := pkg.File(f.URI())
@@ -168,7 +168,7 @@
if err != nil {
return nil, nil, err
}
- if hasListErrors(pkg.GetErrors()) {
+ if hasListErrors(pkg) {
return nil, nil, errors.Errorf("%s has list errors, not running goimports", f.URI())
}
options := &imports.Options{
@@ -269,16 +269,15 @@
// hasParseErrors returns true if the given file has parse errors.
func hasParseErrors(pkg Package, uri span.URI) bool {
for _, err := range pkg.GetErrors() {
- spn := packagesErrorSpan(err)
- if spn.URI() == uri && err.Kind == packages.ParseError {
+ if err.URI == uri && err.Kind == packages.ParseError {
return true
}
}
return false
}
-func hasListErrors(errors []packages.Error) bool {
- for _, err := range errors {
+func hasListErrors(pkg Package) bool {
+ for _, err := range pkg.GetErrors() {
if err.Kind == packages.ListError {
return true
}
diff --git a/internal/lsp/source/view.go b/internal/lsp/source/view.go
index b437b46..a090673 100644
--- a/internal/lsp/source/view.go
+++ b/internal/lsp/source/view.go
@@ -280,7 +280,7 @@
Files() []ParseGoHandle
File(uri span.URI) (ParseGoHandle, error)
GetSyntax(context.Context) []*ast.File
- GetErrors() []packages.Error
+ GetErrors() []Error
GetTypes() *types.Package
GetTypesInfo() *types.Info
GetTypesSizes() types.Sizes
@@ -297,6 +297,17 @@
FindFile(ctx context.Context, uri span.URI) (ParseGoHandle, Package, error)
}
+type Error struct {
+ Msg string
+ URI span.URI
+ Range protocol.Range
+ Kind packages.ErrorKind
+}
+
+func (e *Error) Error() string {
+ return fmt.Sprintf("%s:%s: %s", e.URI, e.Range, e.Msg)
+}
+
type BuiltinPackage interface {
Lookup(name string) *ast.Object
Files() []ParseGoHandle
diff --git a/internal/lsp/testdata/bad/bad0.go b/internal/lsp/testdata/bad/bad0.go
index b178252..5802ac4 100644
--- a/internal/lsp/testdata/bad/bad0.go
+++ b/internal/lsp/testdata/bad/bad0.go
@@ -4,9 +4,9 @@
func stuff() { //@item(stuff, "stuff", "func()", "func")
x := "heeeeyyyy"
- random2(x) //@diag("x", "LSP", "cannot use x (variable of type string) as int value in argument to random2")
+ random2(x) //@diag("x", "compiler", "cannot use x (variable of type string) as int value in argument to random2")
random2(1) //@complete("dom", random, random2, random3)
- y := 3 //@diag("y", "LSP", "y declared but not used")
+ y := 3 //@diag("y", "compiler", "y declared but not used")
}
type bob struct { //@item(bob, "bob", "struct{...}", "struct")
@@ -16,6 +16,6 @@
func _() {
var q int
_ = &bob{
- f: q, //@diag("f", "LSP", "unknown field f in struct literal")
+ f: q, //@diag("f", "compiler", "unknown field f in struct literal")
}
}
diff --git a/internal/lsp/testdata/bad/bad1.go b/internal/lsp/testdata/bad/bad1.go
index 16e6c59..aece2c8 100644
--- a/internal/lsp/testdata/bad/bad1.go
+++ b/internal/lsp/testdata/bad/bad1.go
@@ -2,7 +2,7 @@
package bad
-var a unknown //@item(global_a, "a", "unknown", "var"),diag("unknown", "LSP", "undeclared name: unknown")
+var a unknown //@item(global_a, "a", "unknown", "var"),diag("unknown", "compiler", "undeclared name: unknown")
func random() int { //@item(random, "random", "func() int", "func")
//@complete("", global_a, bob, random, random2, random3, stuff)
@@ -10,9 +10,9 @@
}
func random2(y int) int { //@item(random2, "random2", "func(y int) int", "func"),item(bad_y_param, "y", "int", "var")
- x := 6 //@item(x, "x", "int", "var"),diag("x", "LSP", "x declared but not used")
- var q blah //@item(q, "q", "blah", "var"),diag("q", "LSP", "q declared but not used"),diag("blah", "LSP", "undeclared name: blah")
- var t blob //@item(t, "t", "blob", "var"),diag("t", "LSP", "t declared but not used"),diag("blob", "LSP", "undeclared name: blob")
+ x := 6 //@item(x, "x", "int", "var"),diag("x", "compiler", "x declared but not used")
+ var q blah //@item(q, "q", "blah", "var"),diag("q", "compiler", "q declared but not used"),diag("blah", "compiler", "undeclared name: blah")
+ var t blob //@item(t, "t", "blob", "var"),diag("t", "compiler", "t declared but not used"),diag("blob", "compiler", "undeclared name: blob")
//@complete("", q, t, x, bad_y_param, global_a, bob, random, random2, random3, stuff)
return y
diff --git a/internal/lsp/testdata/bad/badimport.go b/internal/lsp/testdata/bad/badimport.go
index 5e35479..0cce6d5 100644
--- a/internal/lsp/testdata/bad/badimport.go
+++ b/internal/lsp/testdata/bad/badimport.go
@@ -1,5 +1,5 @@
package bad
import (
- _ "nosuchpkg" //@diag("_", "LSP", "could not import nosuchpkg (no package data for import path nosuchpkg)")
+ _ "nosuchpkg" //@diag("_", "compiler", "could not import nosuchpkg (no package data for import path nosuchpkg)")
)
diff --git a/internal/lsp/testdata/badstmt/badstmt.go.in b/internal/lsp/testdata/badstmt/badstmt.go.in
index 05b2c9a..c25b080 100644
--- a/internal/lsp/testdata/badstmt/badstmt.go.in
+++ b/internal/lsp/testdata/badstmt/badstmt.go.in
@@ -5,7 +5,7 @@
)
func _() {
- defer foo.F //@complete(" //", Foo),diag(" //", "LSP", "function must be invoked in defer statement")
+ defer foo.F //@complete(" //", Foo),diag(" //", "syntax", "function must be invoked in defer statement")
y := 1
defer foo.F //@complete(" //", Foo)
}
diff --git a/internal/lsp/testdata/format/bad_format.go.golden b/internal/lsp/testdata/format/bad_format.go.golden
index 31affec..d3a4059 100644
--- a/internal/lsp/testdata/format/bad_format.go.golden
+++ b/internal/lsp/testdata/format/bad_format.go.golden
@@ -9,7 +9,7 @@
func hello() {
- var x int //@diag("x", "LSP", "x declared but not used")
+ var x int //@diag("x", "compiler", "x declared but not used")
}
func hi() {
diff --git a/internal/lsp/testdata/format/bad_format.go.in b/internal/lsp/testdata/format/bad_format.go.in
index 9809a7c..a2da140 100644
--- a/internal/lsp/testdata/format/bad_format.go.in
+++ b/internal/lsp/testdata/format/bad_format.go.in
@@ -11,7 +11,7 @@
- var x int //@diag("x", "LSP", "x declared but not used")
+ var x int //@diag("x", "compiler", "x declared but not used")
}
func hi() {
diff --git a/internal/lsp/testdata/generated/generated.go b/internal/lsp/testdata/generated/generated.go
index abd2bee..27bc69b 100644
--- a/internal/lsp/testdata/generated/generated.go
+++ b/internal/lsp/testdata/generated/generated.go
@@ -3,5 +3,5 @@
// Code generated by generator.go. DO NOT EDIT.
func _() {
- var y int //@diag("y", "LSP", "y declared but not used")
+ var y int //@diag("y", "compiler", "y declared but not used")
}
diff --git a/internal/lsp/testdata/generated/generator.go b/internal/lsp/testdata/generated/generator.go
index 0369987..721703a 100644
--- a/internal/lsp/testdata/generated/generator.go
+++ b/internal/lsp/testdata/generated/generator.go
@@ -1,5 +1,5 @@
package generated
func _() {
- var x int //@diag("x", "LSP", "x declared but not used")
+ var x int //@diag("x", "compiler", "x declared but not used")
}
diff --git a/internal/lsp/testdata/noparse/noparse.go.in b/internal/lsp/testdata/noparse/noparse.go.in
index 52bf306..66a8cce 100644
--- a/internal/lsp/testdata/noparse/noparse.go.in
+++ b/internal/lsp/testdata/noparse/noparse.go.in
@@ -8,4 +8,4 @@
x := 5
}
-func .() {} //@diag(".", "LSP", "expected 'IDENT', found '.'")
+func .() {} //@diag(".", "syntax", "expected 'IDENT', found '.'")
diff --git a/internal/lsp/testdata/noparse_format/noparse_format.go.in b/internal/lsp/testdata/noparse_format/noparse_format.go.in
index 111bb4f..f230a69 100644
--- a/internal/lsp/testdata/noparse_format/noparse_format.go.in
+++ b/internal/lsp/testdata/noparse_format/noparse_format.go.in
@@ -4,6 +4,6 @@
func what() {
var b int
- if { hi() //@diag("{", "LSP", "missing condition in if statement")
+ if { hi() //@diag("{", "syntax", "missing condition in if statement")
}
}
\ No newline at end of file
diff --git a/internal/lsp/testdata/testy/testy_test.go b/internal/lsp/testdata/testy/testy_test.go
index 82e4070..4bc6207 100644
--- a/internal/lsp/testdata/testy/testy_test.go
+++ b/internal/lsp/testdata/testy/testy_test.go
@@ -3,6 +3,6 @@
import "testing"
func TestSomething(t *testing.T) { //@item(TestSomething, "TestSomething(t *testing.T)", "", "func")
- var x int //@mark(testyX, "x"),diag("x", "LSP", "x declared but not used"),refs("x", testyX)
+ var x int //@mark(testyX, "x"),diag("x", "compiler", "x declared but not used"),refs("x", testyX)
a() //@mark(testyA, "a")
}