internal/lsp: use x/xerrors to create new errors

This relates to https://github.com/golang/go/issues/31374 and should switch all instances within `gopls` to use `x/errors` instead of `fmt` to create new errors.

Change-Id: I18339b75d12418d852e0dcc2ba0ed6c2970783b3
GitHub-Last-Rev: f4a55d9b79e7458ef1f1e06cb5eabbabd884f321
GitHub-Pull-Request: golang/tools#108
Reviewed-on: https://go-review.googlesource.com/c/tools/+/179880
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
Jan Steinke 2019-08-06 19:13:11 +00:00 committed by Rebecca Stambler
parent 249e2b9b6d
commit be5259f298
32 changed files with 140 additions and 126 deletions

1
go.mod
View File

@ -5,4 +5,5 @@ go 1.11
require ( require (
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 golang.org/x/net v0.0.0-20190620200207-3b0461eec859
golang.org/x/sync v0.0.0-20190423024810-112230192c58 golang.org/x/sync v0.0.0-20190423024810-112230192c58
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7
) )

2
go.sum
View File

@ -5,3 +5,5 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEha
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -6,7 +6,6 @@ package cache
import ( import (
"context" "context"
"fmt"
"go/ast" "go/ast"
"go/scanner" "go/scanner"
"go/token" "go/token"
@ -20,6 +19,7 @@ import (
"golang.org/x/tools/internal/lsp/telemetry/log" "golang.org/x/tools/internal/lsp/telemetry/log"
"golang.org/x/tools/internal/lsp/telemetry/trace" "golang.org/x/tools/internal/lsp/telemetry/trace"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
errors "golang.org/x/xerrors"
) )
type importer struct { type importer struct {
@ -40,7 +40,7 @@ func (imp *importer) Import(pkgPath string) (*types.Package, error) {
ctx := imp.ctx ctx := imp.ctx
id, ok := imp.view.mcache.ids[packagePath(pkgPath)] id, ok := imp.view.mcache.ids[packagePath(pkgPath)]
if !ok { if !ok {
return nil, fmt.Errorf("no known ID for %s", pkgPath) return nil, errors.Errorf("no known ID for %s", pkgPath)
} }
pkg, err := imp.getPkg(ctx, id) pkg, err := imp.getPkg(ctx, id)
if err != nil { if err != nil {
@ -51,7 +51,7 @@ func (imp *importer) Import(pkgPath string) (*types.Package, error) {
func (imp *importer) getPkg(ctx context.Context, id packageID) (*pkg, error) { func (imp *importer) getPkg(ctx context.Context, id packageID) (*pkg, error) {
if _, ok := imp.seen[id]; ok { if _, ok := imp.seen[id]; ok {
return nil, fmt.Errorf("circular import detected") return nil, errors.Errorf("circular import detected")
} }
imp.view.pcache.mu.Lock() imp.view.pcache.mu.Lock()
e, ok := imp.view.pcache.packages[id] e, ok := imp.view.pcache.packages[id]
@ -99,7 +99,7 @@ func (imp *importer) typeCheck(ctx context.Context, id packageID) (*pkg, error)
defer done() defer done()
meta, ok := imp.view.mcache.packages[id] meta, ok := imp.view.mcache.packages[id]
if !ok { if !ok {
return nil, fmt.Errorf("no metadata for %v", id) return nil, errors.Errorf("no metadata for %v", id)
} }
pkg := &pkg{ pkg := &pkg{
id: meta.id, id: meta.id,
@ -124,7 +124,7 @@ func (imp *importer) typeCheck(ctx context.Context, id packageID) (*pkg, error)
} }
var ( var (
files = make([]*ast.File, len(meta.files)) files = make([]*ast.File, len(meta.files))
errors = make([]error, len(meta.files)) parseErrors = make([]error, len(meta.files))
wg sync.WaitGroup wg sync.WaitGroup
) )
for _, filename := range meta.files { for _, filename := range meta.files {
@ -141,7 +141,7 @@ func (imp *importer) typeCheck(ctx context.Context, id packageID) (*pkg, error)
go func(i int, ph source.ParseGoHandle) { go func(i int, ph source.ParseGoHandle) {
defer wg.Done() defer wg.Done()
files[i], errors[i] = ph.Parse(ctx) files[i], parseErrors[i] = ph.Parse(ctx)
}(i, ph) }(i, ph)
} }
wg.Wait() wg.Wait()
@ -153,7 +153,7 @@ func (imp *importer) typeCheck(ctx context.Context, id packageID) (*pkg, error)
i++ i++
} }
} }
for _, err := range errors { for _, err := range parseErrors {
if err == context.Canceled { if err == context.Canceled {
return nil, err return nil, err
} }
@ -166,7 +166,7 @@ func (imp *importer) typeCheck(ctx context.Context, id packageID) (*pkg, error)
if meta.pkgPath == "unsafe" { if meta.pkgPath == "unsafe" {
pkg.types = types.Unsafe pkg.types = types.Unsafe
} else if len(files) == 0 { // not the unsafe package, no parsed files } else if len(files) == 0 { // not the unsafe package, no parsed files
return nil, fmt.Errorf("no parsed files for package %s", pkg.pkgPath) return nil, errors.Errorf("no parsed files for package %s", pkg.pkgPath)
} else { } else {
pkg.types = types.NewPackage(string(meta.pkgPath), meta.name) pkg.types = types.NewPackage(string(meta.pkgPath), meta.name)
} }
@ -209,14 +209,14 @@ func (imp *importer) cachePackage(ctx context.Context, pkg *pkg, meta *metadata,
uri := ph.File().Identity().URI uri := ph.File().Identity().URI
f, err := imp.view.getFile(ctx, uri) f, err := imp.view.getFile(ctx, uri)
if err != nil { if err != nil {
return fmt.Errorf("no such file %s: %v", uri, err) return errors.Errorf("no such file %s: %v", uri, err)
} }
gof, ok := f.(*goFile) gof, ok := f.(*goFile)
if !ok { if !ok {
return fmt.Errorf("non Go file %s", uri) return errors.Errorf("non Go file %s", uri)
} }
if err := imp.cachePerFile(gof, ph, pkg); err != nil { if err := imp.cachePerFile(gof, ph, pkg); err != nil {
return fmt.Errorf("failed to cache file %s: %v", gof.URI(), err) return errors.Errorf("failed to cache file %s: %v", gof.URI(), err)
} }
} }
@ -246,7 +246,7 @@ func (imp *importer) cachePerFile(gof *goFile, ph source.ParseGoHandle, p *pkg)
file, err := ph.Parse(imp.ctx) file, err := ph.Parse(imp.ctx)
if file == nil { if file == nil {
return fmt.Errorf("no AST for %s: %v", ph.File().Identity().URI, err) return errors.Errorf("no AST for %s: %v", ph.File().Identity().URI, err)
} }
gof.imports = file.Imports gof.imports = file.Imports
return nil return nil

View File

@ -6,7 +6,6 @@ package cache
import ( import (
"context" "context"
"fmt"
"go/ast" "go/ast"
"go/token" "go/token"
"sync" "sync"
@ -15,6 +14,7 @@ import (
"golang.org/x/tools/internal/lsp/telemetry" "golang.org/x/tools/internal/lsp/telemetry"
"golang.org/x/tools/internal/lsp/telemetry/log" "golang.org/x/tools/internal/lsp/telemetry/log"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
errors "golang.org/x/xerrors"
) )
// goFile holds all of the information we know about a Go file. // goFile holds all of the information we know about a Go file.
@ -55,7 +55,7 @@ func (f *goFile) GetToken(ctx context.Context) (*token.File, error) {
} }
tok := f.view.session.cache.fset.File(file.Pos()) tok := f.view.session.cache.fset.File(file.Pos())
if tok == nil { if tok == nil {
return nil, fmt.Errorf("no token.File for %s", f.URI()) return nil, errors.Errorf("no token.File for %s", f.URI())
} }
return tok, nil return tok, nil
} }
@ -67,7 +67,7 @@ func (f *goFile) GetAST(ctx context.Context, mode source.ParseMode) (*ast.File,
if f.isDirty(ctx) || f.wrongParseMode(ctx, mode) { if f.isDirty(ctx) || f.wrongParseMode(ctx, mode) {
if _, err := f.view.loadParseTypecheck(ctx, f); err != nil { if _, err := f.view.loadParseTypecheck(ctx, f); err != nil {
return nil, fmt.Errorf("GetAST: unable to check package for %s: %v", f.URI(), err) return nil, errors.Errorf("GetAST: unable to check package for %s: %v", f.URI(), err)
} }
} }
fh := f.Handle(ctx) fh := f.Handle(ctx)

View File

@ -15,6 +15,7 @@ import (
"golang.org/x/tools/internal/lsp/telemetry/tag" "golang.org/x/tools/internal/lsp/telemetry/tag"
"golang.org/x/tools/internal/lsp/telemetry/trace" "golang.org/x/tools/internal/lsp/telemetry/trace"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
errors "golang.org/x/xerrors"
) )
func (v *view) loadParseTypecheck(ctx context.Context, f *goFile) ([]packages.Error, error) { func (v *view) loadParseTypecheck(ctx context.Context, f *goFile) ([]packages.Error, error) {
@ -55,11 +56,11 @@ func (v *view) loadParseTypecheck(ctx context.Context, f *goFile) ([]packages.Er
return nil, err return nil, err
} }
if pkg == nil || pkg.IsIllTyped() { if pkg == nil || pkg.IsIllTyped() {
return nil, fmt.Errorf("loadParseTypecheck: %s is ill typed", m.pkgPath) return nil, errors.Errorf("loadParseTypecheck: %s is ill typed", m.pkgPath)
} }
} }
if len(f.pkgs) == 0 { if len(f.pkgs) == 0 {
return nil, fmt.Errorf("no packages found for %s", f.URI()) return nil, errors.Errorf("no packages found for %s", f.URI())
} }
return nil, nil return nil, nil
} }
@ -93,7 +94,7 @@ func (v *view) checkMetadata(ctx context.Context, f *goFile) (map[packageID]*met
pkgs, err := packages.Load(v.Config(ctx), fmt.Sprintf("file=%s", f.filename())) pkgs, err := packages.Load(v.Config(ctx), fmt.Sprintf("file=%s", f.filename()))
if len(pkgs) == 0 { if len(pkgs) == 0 {
if err == nil { if err == nil {
err = fmt.Errorf("go/packages.Load: no packages found for %s", f.filename()) err = errors.Errorf("go/packages.Load: no packages found for %s", f.filename())
} }
// Return this error as a diagnostic to the user. // Return this error as a diagnostic to the user.
return nil, []packages.Error{ return nil, []packages.Error{
@ -112,7 +113,7 @@ func (v *view) checkMetadata(ctx context.Context, f *goFile) (map[packageID]*met
// If the package comes back with errors from `go list`, // If the package comes back with errors from `go list`,
// don't bother type-checking it. // don't bother type-checking it.
if len(pkg.Errors) > 0 { if len(pkg.Errors) > 0 {
return nil, pkg.Errors, fmt.Errorf("package %s has errors, skipping type-checking", pkg.PkgPath) return nil, pkg.Errors, errors.Errorf("package %s has errors, skipping type-checking", pkg.PkgPath)
} }
// Build the import graph for this package. // Build the import graph for this package.
if err := v.link(ctx, packagePath(pkg.PkgPath), pkg, nil, missingImports); err != nil { if err := v.link(ctx, packagePath(pkg.PkgPath), pkg, nil, missingImports); err != nil {
@ -132,7 +133,7 @@ func validateMetadata(ctx context.Context, missingImports map[packagePath]struct
// If `go list` failed to get data for the file in question (this should never happen). // If `go list` failed to get data for the file in question (this should never happen).
if len(f.meta) == 0 { if len(f.meta) == 0 {
return nil, fmt.Errorf("loadParseTypecheck: no metadata found for %v", f.filename()) return nil, errors.Errorf("loadParseTypecheck: no metadata found for %v", f.filename())
} }
// If we have already seen these missing imports before, and we have type information, // If we have already seen these missing imports before, and we have type information,
@ -254,7 +255,7 @@ func (v *view) link(ctx context.Context, pkgPath packagePath, pkg *packages.Pack
for importPath, importPkg := range pkg.Imports { for importPath, importPkg := range pkg.Imports {
importPkgPath := packagePath(importPath) importPkgPath := packagePath(importPath)
if importPkgPath == pkgPath { if importPkgPath == pkgPath {
return fmt.Errorf("cycle detected in %s", importPath) return errors.Errorf("cycle detected in %s", importPath)
} }
// Don't remember any imports with significant errors. // Don't remember any imports with significant errors.
if importPkgPath != "unsafe" && len(pkg.CompiledGoFiles) == 0 { if importPkgPath != "unsafe" && len(pkg.CompiledGoFiles) == 0 {

View File

@ -6,8 +6,9 @@ package cache
import ( import (
"context" "context"
"fmt"
"go/token" "go/token"
errors "golang.org/x/xerrors"
) )
// modFile holds all of the information we know about a mod file. // modFile holds all of the information we know about a mod file.
@ -16,7 +17,7 @@ type modFile struct {
} }
func (*modFile) GetToken(context.Context) (*token.File, error) { func (*modFile) GetToken(context.Context) (*token.File, error) {
return nil, fmt.Errorf("GetToken: not implemented") return nil, errors.Errorf("GetToken: not implemented")
} }
func (*modFile) setContent(content []byte) {} func (*modFile) setContent(content []byte) {}

View File

@ -6,7 +6,6 @@ package cache
import ( import (
"context" "context"
"fmt"
"go/ast" "go/ast"
"go/parser" "go/parser"
"go/scanner" "go/scanner"
@ -16,6 +15,7 @@ import (
"golang.org/x/tools/internal/lsp/telemetry" "golang.org/x/tools/internal/lsp/telemetry"
"golang.org/x/tools/internal/lsp/telemetry/trace" "golang.org/x/tools/internal/lsp/telemetry/trace"
"golang.org/x/tools/internal/memoize" "golang.org/x/tools/internal/memoize"
errors "golang.org/x/xerrors"
) )
// Limits the number of parallel parser calls per process. // Limits the number of parallel parser calls per process.
@ -154,7 +154,7 @@ func fix(ctx context.Context, file *ast.File, tok *token.File, src []byte) error
case *ast.BadStmt: case *ast.BadStmt:
err = parseDeferOrGoStmt(n, parent, tok, src) // don't shadow err err = parseDeferOrGoStmt(n, parent, tok, src) // don't shadow err
if err != nil { if err != nil {
err = fmt.Errorf("unable to parse defer or go from *ast.BadStmt: %v", err) err = errors.Errorf("unable to parse defer or go from *ast.BadStmt: %v", err)
} }
return false return false
default: default:
@ -182,7 +182,7 @@ func parseDeferOrGoStmt(bad *ast.BadStmt, parent ast.Node, tok *token.File, src
var lit string var lit string
for { for {
if tkn == token.EOF { if tkn == token.EOF {
return fmt.Errorf("reached the end of the file") return errors.Errorf("reached the end of the file")
} }
if pos >= bad.From { if pos >= bad.From {
break break
@ -200,7 +200,7 @@ func parseDeferOrGoStmt(bad *ast.BadStmt, parent ast.Node, tok *token.File, src
Go: pos, Go: pos,
} }
default: default:
return fmt.Errorf("no defer or go statement found") return errors.Errorf("no defer or go statement found")
} }
// The expression after the "defer" or "go" starts at this position. // The expression after the "defer" or "go" starts at this position.
@ -225,15 +225,15 @@ FindTo:
to = curr to = curr
} }
if !from.IsValid() || tok.Offset(from) >= len(src) { if !from.IsValid() || tok.Offset(from) >= len(src) {
return fmt.Errorf("invalid from position") return errors.Errorf("invalid from position")
} }
if !to.IsValid() || tok.Offset(to)+1 >= len(src) { if !to.IsValid() || tok.Offset(to)+1 >= len(src) {
return fmt.Errorf("invalid to position") return errors.Errorf("invalid to position")
} }
exprstr := string(src[tok.Offset(from) : tok.Offset(to)+1]) exprstr := string(src[tok.Offset(from) : tok.Offset(to)+1])
expr, err := parser.ParseExpr(exprstr) expr, err := parser.ParseExpr(exprstr)
if expr == nil { if expr == nil {
return fmt.Errorf("no expr in %s: %v", exprstr, err) return errors.Errorf("no expr in %s: %v", exprstr, err)
} }
// parser.ParseExpr returns undefined positions. // parser.ParseExpr returns undefined positions.
// Adjust them for the current file. // Adjust them for the current file.

View File

@ -6,7 +6,6 @@ package cache
import ( import (
"context" "context"
"fmt"
"os" "os"
"sort" "sort"
"strconv" "strconv"
@ -21,6 +20,7 @@ import (
"golang.org/x/tools/internal/lsp/telemetry/trace" "golang.org/x/tools/internal/lsp/telemetry/trace"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/xcontext" "golang.org/x/tools/internal/xcontext"
errors "golang.org/x/xerrors"
) )
type session struct { type session struct {
@ -178,7 +178,7 @@ func (s *session) removeView(ctx context.Context, view *view) error {
return nil return nil
} }
} }
return fmt.Errorf("view %s for %v not found", view.Name(), view.Folder()) return errors.Errorf("view %s for %v not found", view.Name(), view.Folder())
} }
// TODO: Propagate the language ID through to the view. // TODO: Propagate the language ID through to the view.

View File

@ -6,8 +6,9 @@ package cache
import ( import (
"context" "context"
"fmt"
"go/token" "go/token"
errors "golang.org/x/xerrors"
) )
// sumFile holds all of the information we know about a sum file. // sumFile holds all of the information we know about a sum file.
@ -16,7 +17,7 @@ type sumFile struct {
} }
func (*sumFile) GetToken(context.Context) (*token.File, error) { func (*sumFile) GetToken(context.Context) (*token.File, error) {
return nil, fmt.Errorf("GetToken: not implemented") return nil, errors.Errorf("GetToken: not implemented")
} }
func (*sumFile) setContent(content []byte) {} func (*sumFile) setContent(content []byte) {}

View File

@ -6,11 +6,11 @@ package cache
import ( import (
"context" "context"
"fmt"
"go/token" "go/token"
"golang.org/x/tools/internal/lsp/source" "golang.org/x/tools/internal/lsp/source"
"golang.org/x/tools/internal/memoize" "golang.org/x/tools/internal/memoize"
errors "golang.org/x/xerrors"
) )
type tokenKey struct { type tokenKey struct {
@ -87,7 +87,7 @@ func tokenFile(ctx context.Context, c *cache, fh source.FileHandle) (*token.File
} }
tok := c.FileSet().AddFile(fh.Identity().URI.Filename(), -1, len(buf)) tok := c.FileSet().AddFile(fh.Identity().URI.Filename(), -1, len(buf))
if tok == nil { if tok == nil {
return nil, fmt.Errorf("no token.File for %s", fh.Identity().URI) return nil, errors.Errorf("no token.File for %s", fh.Identity().URI)
} }
tok.SetLinesForContent(buf) tok.SetLinesForContent(buf)
return tok, nil return tok, nil

View File

@ -11,6 +11,7 @@ import (
"time" "time"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
errors "golang.org/x/xerrors"
) )
// check implements the check verb for gopls. // check implements the check verb for gopls.
@ -60,14 +61,14 @@ func (c *check) Run(ctx context.Context, args ...string) error {
select { select {
case <-file.hasDiagnostics: case <-file.hasDiagnostics:
case <-time.After(30 * time.Second): case <-time.After(30 * time.Second):
return fmt.Errorf("timed out waiting for results from %v", file.uri) return errors.Errorf("timed out waiting for results from %v", file.uri)
} }
file.diagnosticsMu.Lock() file.diagnosticsMu.Lock()
defer file.diagnosticsMu.Unlock() defer file.diagnosticsMu.Unlock()
for _, d := range file.diagnostics { for _, d := range file.diagnostics {
spn, err := file.mapper.RangeSpan(d.Range) spn, err := file.mapper.RangeSpan(d.Range)
if err != nil { if err != nil {
return fmt.Errorf("Could not convert position %v for %q", d.Range, d.Message) return errors.Errorf("Could not convert position %v for %q", d.Range, d.Message)
} }
fmt.Printf("%v: %v\n", spn, d.Message) fmt.Printf("%v: %v\n", spn, d.Message)
} }

View File

@ -28,6 +28,7 @@ import (
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/tool" "golang.org/x/tools/internal/tool"
"golang.org/x/tools/internal/xcontext" "golang.org/x/tools/internal/xcontext"
errors "golang.org/x/xerrors"
) )
// Application is the main application as passed to tool.Main // Application is the main application as passed to tool.Main
@ -335,7 +336,7 @@ func (c *cmdClient) getFile(ctx context.Context, uri span.URI) *cmdFile {
fname := uri.Filename() fname := uri.Filename()
content, err := ioutil.ReadFile(fname) content, err := ioutil.ReadFile(fname)
if err != nil { if err != nil {
file.err = fmt.Errorf("getFile %v: %v", uri, err) file.err = errors.Errorf("getFile: %v: %v", uri, err)
return file return file
} }
f := c.fset.AddFile(fname, -1, len(content)) f := c.fset.AddFile(fname, -1, len(content))
@ -366,7 +367,7 @@ func (c *connection) AddFile(ctx context.Context, uri span.URI) *cmdFile {
p.TextDocument.Text = string(file.mapper.Content) p.TextDocument.Text = string(file.mapper.Content)
p.TextDocument.LanguageID = source.DetectLanguage("", file.uri.Filename()).String() p.TextDocument.LanguageID = source.DetectLanguage("", file.uri.Filename()).String()
if err := c.Server.DidOpen(ctx, p); err != nil { if err := c.Server.DidOpen(ctx, p); err != nil {
file.err = fmt.Errorf("%v: %v", uri, err) file.err = errors.Errorf("%v: %v", uri, err)
} }
return file return file
} }

View File

@ -16,6 +16,7 @@ import (
"golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/protocol"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/tool" "golang.org/x/tools/internal/tool"
errors "golang.org/x/xerrors"
) )
// A Definition is the result of a 'definition' query. // A Definition is the result of a 'definition' query.
@ -79,26 +80,26 @@ func (d *definition) Run(ctx context.Context, args ...string) error {
} }
locs, err := conn.Definition(ctx, &p) locs, err := conn.Definition(ctx, &p)
if err != nil { if err != nil {
return fmt.Errorf("%v: %v", from, err) return errors.Errorf("%v: %v", from, err)
} }
if len(locs) == 0 { if len(locs) == 0 {
return fmt.Errorf("%v: not an identifier", from) return errors.Errorf("%v: not an identifier", from)
} }
hover, err := conn.Hover(ctx, &p) hover, err := conn.Hover(ctx, &p)
if err != nil { if err != nil {
return fmt.Errorf("%v: %v", from, err) return errors.Errorf("%v: %v", from, err)
} }
if hover == nil { if hover == nil {
return fmt.Errorf("%v: not an identifier", from) return errors.Errorf("%v: not an identifier", from)
} }
file = conn.AddFile(ctx, span.NewURI(locs[0].URI)) file = conn.AddFile(ctx, span.NewURI(locs[0].URI))
if file.err != nil { if file.err != nil {
return fmt.Errorf("%v: %v", from, file.err) return errors.Errorf("%v: %v", from, file.err)
} }
definition, err := file.mapper.Span(locs[0]) definition, err := file.mapper.Span(locs[0])
if err != nil { if err != nil {
return fmt.Errorf("%v: %v", from, err) return errors.Errorf("%v: %v", from, err)
} }
description := strings.TrimSpace(hover.Contents.Value) description := strings.TrimSpace(hover.Contents.Value)
var result interface{} var result interface{}
@ -115,7 +116,7 @@ func (d *definition) Run(ctx context.Context, args ...string) error {
Desc: description, Desc: description,
} }
default: default:
return fmt.Errorf("unknown emulation for definition: %s", d.query.Emulate) return errors.Errorf("unknown emulation for definition: %s", d.query.Emulate)
} }
if err != nil { if err != nil {
return err return err
@ -131,7 +132,7 @@ func (d *definition) Run(ctx context.Context, args ...string) error {
case *guru.Definition: case *guru.Definition:
fmt.Printf("%s: defined here as %s", d.ObjPos, d.Desc) fmt.Printf("%s: defined here as %s", d.ObjPos, d.Desc)
default: default:
return fmt.Errorf("no printer for type %T", result) return errors.Errorf("no printer for type %T", result)
} }
return nil return nil
} }

View File

@ -16,6 +16,7 @@ import (
"golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/protocol"
"golang.org/x/tools/internal/lsp/source" "golang.org/x/tools/internal/lsp/source"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
errors "golang.org/x/xerrors"
) )
// format implements the format verb for gopls. // format implements the format verb for gopls.
@ -68,18 +69,18 @@ func (f *format) Run(ctx context.Context, args ...string) error {
return err return err
} }
if loc.Range.Start != loc.Range.End { if loc.Range.Start != loc.Range.End {
return fmt.Errorf("only full file formatting supported") return errors.Errorf("only full file formatting supported")
} }
p := protocol.DocumentFormattingParams{ p := protocol.DocumentFormattingParams{
TextDocument: protocol.TextDocumentIdentifier{URI: loc.URI}, TextDocument: protocol.TextDocumentIdentifier{URI: loc.URI},
} }
edits, err := conn.Formatting(ctx, &p) edits, err := conn.Formatting(ctx, &p)
if err != nil { if err != nil {
return fmt.Errorf("%v: %v", spn, err) return errors.Errorf("%v: %v", spn, err)
} }
sedits, err := lsp.FromProtocolEdits(file.mapper, edits) sedits, err := lsp.FromProtocolEdits(file.mapper, edits)
if err != nil { if err != nil {
return fmt.Errorf("%v: %v", spn, err) return errors.Errorf("%v: %v", spn, err)
} }
ops := source.EditsToDiff(sedits) ops := source.EditsToDiff(sedits)
lines := diff.SplitLines(string(file.mapper.Content)) lines := diff.SplitLines(string(file.mapper.Content))

View File

@ -24,6 +24,7 @@ import (
"golang.org/x/tools/internal/lsp/telemetry/tag" "golang.org/x/tools/internal/lsp/telemetry/tag"
"golang.org/x/tools/internal/lsp/telemetry/trace" "golang.org/x/tools/internal/lsp/telemetry/trace"
"golang.org/x/tools/internal/tool" "golang.org/x/tools/internal/tool"
errors "golang.org/x/xerrors"
) )
// Serve is a struct that exposes the configurable parts of the LSP server as // Serve is a struct that exposes the configurable parts of the LSP server as
@ -68,7 +69,7 @@ func (s *Serve) Run(ctx context.Context, args ...string) error {
} }
f, err := os.Create(filename) f, err := os.Create(filename)
if err != nil { if err != nil {
return fmt.Errorf("Unable to create log file: %v", err) return errors.Errorf("Unable to create log file: %v", err)
} }
defer f.Close() defer f.Close()
log.SetOutput(io.MultiWriter(os.Stderr, f)) log.SetOutput(io.MultiWriter(os.Stderr, f))

View File

@ -15,6 +15,7 @@ import (
"golang.org/x/tools/internal/lsp/telemetry" "golang.org/x/tools/internal/lsp/telemetry"
"golang.org/x/tools/internal/lsp/telemetry/log" "golang.org/x/tools/internal/lsp/telemetry/log"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
errors "golang.org/x/xerrors"
) )
func (s *Server) codeAction(ctx context.Context, params *protocol.CodeActionParams) ([]protocol.CodeAction, error) { func (s *Server) codeAction(ctx context.Context, params *protocol.CodeActionParams) ([]protocol.CodeAction, error) {
@ -44,7 +45,7 @@ func (s *Server) codeAction(ctx context.Context, params *protocol.CodeActionPara
} }
} }
if len(wanted) == 0 { if len(wanted) == 0 {
return nil, fmt.Errorf("no supported code action to execute for %s, wanted %v", uri, params.Context.Only) return nil, errors.Errorf("no supported code action to execute for %s, wanted %v", uri, params.Context.Only)
} }
spn, err := m.RangeSpan(params.Range) spn, err := m.RangeSpan(params.Range)

View File

@ -18,6 +18,7 @@ import (
"golang.org/x/tools/internal/lsp/telemetry/log" "golang.org/x/tools/internal/lsp/telemetry/log"
"golang.org/x/tools/internal/lsp/telemetry/tag" "golang.org/x/tools/internal/lsp/telemetry/tag"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
errors "golang.org/x/xerrors"
) )
func (s *Server) initialize(ctx context.Context, params *protocol.InitializeParams) (*protocol.InitializeResult, error) { func (s *Server) initialize(ctx context.Context, params *protocol.InitializeParams) (*protocol.InitializeResult, error) {
@ -64,7 +65,7 @@ func (s *Server) initialize(ctx context.Context, params *protocol.InitializePara
// no folders and no root, single file mode // no folders and no root, single file mode
//TODO(iancottrell): not sure how to do single file mode yet //TODO(iancottrell): not sure how to do single file mode yet
//issue: golang.org/issue/31168 //issue: golang.org/issue/31168
return nil, fmt.Errorf("single file mode not supported yet") return nil, errors.Errorf("single file mode not supported yet")
} }
} }
@ -191,13 +192,13 @@ func (s *Server) processConfig(ctx context.Context, view source.View, config int
} }
c, ok := config.(map[string]interface{}) c, ok := config.(map[string]interface{})
if !ok { if !ok {
return fmt.Errorf("invalid config gopls type %T", config) return errors.Errorf("invalid config gopls type %T", config)
} }
// Get the environment for the go/packages config. // Get the environment for the go/packages config.
if env := c["env"]; env != nil { if env := c["env"]; env != nil {
menv, ok := env.(map[string]interface{}) menv, ok := env.(map[string]interface{})
if !ok { if !ok {
return fmt.Errorf("invalid config gopls.env type %T", env) return errors.Errorf("invalid config gopls.env type %T", env)
} }
env := view.Env() env := view.Env()
for k, v := range menv { for k, v := range menv {
@ -209,7 +210,7 @@ func (s *Server) processConfig(ctx context.Context, view source.View, config int
if buildFlags := c["buildFlags"]; buildFlags != nil { if buildFlags := c["buildFlags"]; buildFlags != nil {
iflags, ok := buildFlags.([]interface{}) iflags, ok := buildFlags.([]interface{})
if !ok { if !ok {
return fmt.Errorf("invalid config gopls.buildFlags type %T", buildFlags) return errors.Errorf("invalid config gopls.buildFlags type %T", buildFlags)
} }
flags := make([]string, 0, len(iflags)) flags := make([]string, 0, len(iflags))
for _, flag := range iflags { for _, flag := range iflags {

View File

@ -6,7 +6,6 @@ package lsp
import ( import (
"context" "context"
"fmt"
"go/ast" "go/ast"
"go/token" "go/token"
"regexp" "regexp"
@ -18,6 +17,7 @@ import (
"golang.org/x/tools/internal/lsp/telemetry/log" "golang.org/x/tools/internal/lsp/telemetry/log"
"golang.org/x/tools/internal/lsp/telemetry/tag" "golang.org/x/tools/internal/lsp/telemetry/tag"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
errors "golang.org/x/xerrors"
) )
func (s *Server) documentLink(ctx context.Context, params *protocol.DocumentLinkParams) ([]protocol.DocumentLink, error) { func (s *Server) documentLink(ctx context.Context, params *protocol.DocumentLinkParams) ([]protocol.DocumentLink, error) {
@ -82,7 +82,7 @@ func findLinksInString(src string, pos token.Pos, view source.View, mapper *prot
var links []protocol.DocumentLink var links []protocol.DocumentLink
re, err := getURLRegexp() re, err := getURLRegexp()
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot create regexp for links: %s", err.Error()) return nil, errors.Errorf("cannot create regexp for links: %s", err.Error())
} }
for _, urlIndex := range re.FindAllIndex([]byte(src), -1) { for _, urlIndex := range re.FindAllIndex([]byte(src), -1) {
start := urlIndex[0] start := urlIndex[0]

View File

@ -7,10 +7,10 @@
package protocol package protocol
import ( import (
"fmt"
"go/token" "go/token"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
errors "golang.org/x/xerrors"
) )
type ColumnMapper struct { type ColumnMapper struct {
@ -47,7 +47,7 @@ func (m *ColumnMapper) Location(s span.Span) (Location, error) {
func (m *ColumnMapper) Range(s span.Span) (Range, error) { func (m *ColumnMapper) Range(s span.Span) (Range, error) {
if span.CompareURI(m.URI, s.URI()) != 0 { if span.CompareURI(m.URI, s.URI()) != 0 {
return Range{}, fmt.Errorf("column mapper is for file %q instead of %q", m.URI, s.URI()) return Range{}, errors.Errorf("column mapper is for file %q instead of %q", m.URI, s.URI())
} }
s, err := s.WithAll(m.Converter) s, err := s.WithAll(m.Converter)
if err != nil { if err != nil {

View File

@ -20,6 +20,7 @@ import (
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis"
"golang.org/x/tools/internal/lsp/telemetry/trace" "golang.org/x/tools/internal/lsp/telemetry/trace"
errors "golang.org/x/xerrors"
) )
func analyze(ctx context.Context, v View, pkgs []Package, analyzers []*analysis.Analyzer) ([]*Action, error) { func analyze(ctx context.Context, v View, pkgs []Package, analyzers []*analysis.Analyzer) ([]*Action, error) {
@ -119,7 +120,7 @@ func (act *Action) execOnce(ctx context.Context, fset *token.FileSet) error {
} }
if failed != nil { if failed != nil {
sort.Strings(failed) sort.Strings(failed)
act.err = fmt.Errorf("failed prerequisites: %s", strings.Join(failed, ", ")) act.err = errors.Errorf("failed prerequisites: %s", strings.Join(failed, ", "))
return act.err return act.err
} }
@ -163,12 +164,12 @@ func (act *Action) execOnce(ctx context.Context, fset *token.FileSet) error {
act.pass = pass act.pass = pass
if act.Pkg.IsIllTyped() && !pass.Analyzer.RunDespiteErrors { if act.Pkg.IsIllTyped() && !pass.Analyzer.RunDespiteErrors {
act.err = fmt.Errorf("analysis skipped due to errors in package: %v", act.Pkg.GetErrors()) act.err = errors.Errorf("analysis skipped due to errors in package: %v", act.Pkg.GetErrors())
} else { } else {
act.result, act.err = pass.Analyzer.Run(pass) act.result, act.err = pass.Analyzer.Run(pass)
if act.err == nil { if act.err == nil {
if got, want := reflect.TypeOf(act.result), pass.Analyzer.ResultType; got != want { if got, want := reflect.TypeOf(act.result), pass.Analyzer.ResultType; got != want {
act.err = fmt.Errorf( act.err = errors.Errorf(
"internal error: on package %s, analyzer %s returned a result of type %v, but declared ResultType %v", "internal error: on package %s, analyzer %s returned a result of type %v, but declared ResultType %v",
pass.Pkg.Path(), pass.Analyzer, got, want) pass.Pkg.Path(), pass.Analyzer, got, want)
} }

View File

@ -6,7 +6,6 @@ package source
import ( import (
"context" "context"
"fmt"
"go/ast" "go/ast"
"go/token" "go/token"
"go/types" "go/types"
@ -16,6 +15,7 @@ import (
"golang.org/x/tools/internal/lsp/snippet" "golang.org/x/tools/internal/lsp/snippet"
"golang.org/x/tools/internal/lsp/telemetry/trace" "golang.org/x/tools/internal/lsp/telemetry/trace"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
errors "golang.org/x/xerrors"
) )
type CompletionItem struct { type CompletionItem struct {
@ -212,7 +212,7 @@ func (c *completer) setSurrounding(ident *ast.Ident) {
// members for more candidates. // members for more candidates.
func (c *completer) found(obj types.Object, score float64) error { func (c *completer) found(obj types.Object, score float64) error {
if obj.Pkg() != nil && obj.Pkg() != c.types && !obj.Exported() { if obj.Pkg() != nil && obj.Pkg() != c.types && !obj.Exported() {
return fmt.Errorf("%s is inaccessible from %s", obj.Name(), c.types.Path()) return errors.Errorf("%s is inaccessible from %s", obj.Name(), c.types.Path())
} }
if c.inDeepCompletion() { if c.inDeepCompletion() {
@ -287,14 +287,14 @@ func Completion(ctx context.Context, view View, f GoFile, pos token.Pos, opts Co
} }
pkg := f.GetPackage(ctx) pkg := f.GetPackage(ctx)
if pkg == nil || pkg.IsIllTyped() { if pkg == nil || pkg.IsIllTyped() {
return nil, nil, fmt.Errorf("package for %s is ill typed", f.URI()) return nil, nil, errors.Errorf("package for %s is ill typed", f.URI())
} }
// Completion is based on what precedes the cursor. // Completion is based on what precedes the cursor.
// Find the path to the position before pos. // Find the path to the position before pos.
path, _ := astutil.PathEnclosingInterval(file, pos-1, pos-1) path, _ := astutil.PathEnclosingInterval(file, pos-1, pos-1)
if path == nil { if path == nil {
return nil, nil, fmt.Errorf("cannot find node enclosing position") return nil, nil, errors.Errorf("cannot find node enclosing position")
} }
// Skip completion inside comments. // Skip completion inside comments.
for _, g := range file.Comments { for _, g := range file.Comments {
@ -358,7 +358,7 @@ func Completion(ctx context.Context, view View, f GoFile, pos token.Pos, opts Co
qual := types.RelativeTo(pkg.GetTypes()) qual := types.RelativeTo(pkg.GetTypes())
of += ", of " + types.ObjectString(obj, qual) of += ", of " + types.ObjectString(obj, qual)
} }
return nil, nil, fmt.Errorf("this is a definition%s", of) return nil, nil, errors.Errorf("this is a definition%s", of)
} }
} }
if err := c.lexical(); err != nil { if err := c.lexical(); err != nil {
@ -423,7 +423,7 @@ func (c *completer) selector(sel *ast.SelectorExpr) error {
// Invariant: sel is a true selector. // Invariant: sel is a true selector.
tv, ok := c.info.Types[sel.X] tv, ok := c.info.Types[sel.X]
if !ok { if !ok {
return fmt.Errorf("cannot resolve %s", sel.X) return errors.Errorf("cannot resolve %s", sel.X)
} }
return c.methodsAndFields(tv.Type, tv.Addressable()) return c.methodsAndFields(tv.Type, tv.Addressable())

View File

@ -8,7 +8,6 @@ package source
import ( import (
"bytes" "bytes"
"context" "context"
"fmt"
"go/format" "go/format"
"golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/go/ast/astutil"
@ -18,6 +17,7 @@ import (
"golang.org/x/tools/internal/lsp/telemetry/log" "golang.org/x/tools/internal/lsp/telemetry/log"
"golang.org/x/tools/internal/lsp/telemetry/trace" "golang.org/x/tools/internal/lsp/telemetry/trace"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
errors "golang.org/x/xerrors"
) )
// Format formats a file with a given range. // Format formats a file with a given range.
@ -43,7 +43,7 @@ func Format(ctx context.Context, f GoFile, rng span.Range) ([]TextEdit, error) {
} }
path, exact := astutil.PathEnclosingInterval(file, rng.Start, rng.End) path, exact := astutil.PathEnclosingInterval(file, rng.Start, rng.End)
if !exact || len(path) == 0 { if !exact || len(path) == 0 {
return nil, fmt.Errorf("no exact AST node matching the specified range") return nil, errors.Errorf("no exact AST node matching the specified range")
} }
node := path[0] node := path[0]
@ -80,10 +80,10 @@ func Imports(ctx context.Context, view View, f GoFile, rng span.Range) ([]TextEd
} }
pkg := f.GetPackage(ctx) pkg := f.GetPackage(ctx)
if pkg == nil || pkg.IsIllTyped() { if pkg == nil || pkg.IsIllTyped() {
return nil, fmt.Errorf("no package for file %s", f.URI()) return nil, errors.Errorf("no package for file %s", f.URI())
} }
if hasListErrors(pkg.GetErrors()) { if hasListErrors(pkg.GetErrors()) {
return nil, fmt.Errorf("%s has list errors, not running goimports", f.URI()) return nil, errors.Errorf("%s has list errors, not running goimports", f.URI())
} }
options := &imports.Options{ options := &imports.Options{
@ -125,10 +125,10 @@ func AllImportsFixes(ctx context.Context, view View, f GoFile, rng span.Range) (
} }
pkg := f.GetPackage(ctx) pkg := f.GetPackage(ctx)
if pkg == nil || pkg.IsIllTyped() { if pkg == nil || pkg.IsIllTyped() {
return nil, nil, fmt.Errorf("no package for file %s", f.URI()) return nil, nil, errors.Errorf("no package for file %s", f.URI())
} }
if hasListErrors(pkg.GetErrors()) { if hasListErrors(pkg.GetErrors()) {
return nil, nil, fmt.Errorf("%s has list errors, not running goimports", f.URI()) return nil, nil, errors.Errorf("%s has list errors, not running goimports", f.URI())
} }
options := &imports.Options{ options := &imports.Options{

View File

@ -6,13 +6,13 @@ package source
import ( import (
"context" "context"
"fmt"
"go/ast" "go/ast"
"go/token" "go/token"
"golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/go/ast/astutil"
"golang.org/x/tools/internal/lsp/telemetry/trace" "golang.org/x/tools/internal/lsp/telemetry/trace"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
errors "golang.org/x/xerrors"
) )
func Highlight(ctx context.Context, f GoFile, pos token.Pos) ([]span.Span, error) { func Highlight(ctx context.Context, f GoFile, pos token.Pos) ([]span.Span, error) {
@ -26,11 +26,11 @@ func Highlight(ctx context.Context, f GoFile, pos token.Pos) ([]span.Span, error
fset := f.FileSet() fset := f.FileSet()
path, _ := astutil.PathEnclosingInterval(file, pos, pos) path, _ := astutil.PathEnclosingInterval(file, pos, pos)
if len(path) == 0 { if len(path) == 0 {
return nil, fmt.Errorf("no enclosing position found for %s", fset.Position(pos)) return nil, errors.Errorf("no enclosing position found for %s", fset.Position(pos))
} }
id, ok := path[0].(*ast.Ident) id, ok := path[0].(*ast.Ident)
if !ok { if !ok {
return nil, fmt.Errorf("%s is not an identifier", fset.Position(pos)) return nil, errors.Errorf("%s is not an identifier", fset.Position(pos))
} }
var result []span.Span var result []span.Span
if id.Obj != nil { if id.Obj != nil {

View File

@ -6,7 +6,6 @@ package source
import ( import (
"context" "context"
"fmt"
"go/ast" "go/ast"
"go/doc" "go/doc"
"go/format" "go/format"
@ -14,6 +13,7 @@ import (
"strings" "strings"
"golang.org/x/tools/internal/lsp/telemetry/trace" "golang.org/x/tools/internal/lsp/telemetry/trace"
errors "golang.org/x/xerrors"
) )
type documentation struct { type documentation struct {
@ -129,7 +129,7 @@ func formatGenDecl(node *ast.GenDecl, obj types.Object, typ types.Type) (*docume
} }
} }
if spec == nil { if spec == nil {
return nil, fmt.Errorf("no spec for node %v at position %v", node, obj.Pos()) return nil, errors.Errorf("no spec for node %v at position %v", node, obj.Pos())
} }
// If we have a field or method. // If we have a field or method.
switch obj.(type) { switch obj.(type) {
@ -150,7 +150,7 @@ func formatGenDecl(node *ast.GenDecl, obj types.Object, typ types.Type) (*docume
case *ast.ImportSpec: case *ast.ImportSpec:
return &documentation{spec, spec.Doc}, nil return &documentation{spec, spec.Doc}, nil
} }
return nil, fmt.Errorf("unable to format spec %v (%T)", spec, spec) return nil, errors.Errorf("unable to format spec %v (%T)", spec, spec)
} }
func formatVar(node ast.Spec, obj types.Object) (*documentation, error) { func formatVar(node ast.Spec, obj types.Object) (*documentation, error) {

View File

@ -6,7 +6,6 @@ package source
import ( import (
"context" "context"
"fmt"
"go/ast" "go/ast"
"go/token" "go/token"
"go/types" "go/types"
@ -15,6 +14,7 @@ import (
"golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/go/ast/astutil"
"golang.org/x/tools/internal/lsp/telemetry/trace" "golang.org/x/tools/internal/lsp/telemetry/trace"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
errors "golang.org/x/xerrors"
) )
// IdentifierInfo holds information about an identifier in Go source. // IdentifierInfo holds information about an identifier in Go source.
@ -56,7 +56,7 @@ func Identifier(ctx context.Context, view View, f GoFile, pos token.Pos) (*Ident
// requesting a completion), use the path to the preceding node. // requesting a completion), use the path to the preceding node.
result, err := identifier(ctx, view, f, pos-1) result, err := identifier(ctx, view, f, pos-1)
if result == nil && err == nil { if result == nil && err == nil {
err = fmt.Errorf("no identifier found") err = errors.Errorf("no identifier found")
} }
return result, err return result, err
} }
@ -72,7 +72,7 @@ func identifier(ctx context.Context, view View, f GoFile, pos token.Pos) (*Ident
} }
pkg := f.GetPackage(ctx) pkg := f.GetPackage(ctx)
if pkg == nil || pkg.IsIllTyped() { if pkg == nil || pkg.IsIllTyped() {
return nil, fmt.Errorf("pkg for %s is ill-typed", f.URI()) return nil, errors.Errorf("pkg for %s is ill-typed", f.URI())
} }
// Handle import specs separately, as there is no formal position for a package declaration. // Handle import specs separately, as there is no formal position for a package declaration.
if result, err := importSpec(ctx, f, file, pkg, pos); result != nil || err != nil { if result, err := importSpec(ctx, f, file, pkg, pos); result != nil || err != nil {
@ -80,7 +80,7 @@ func identifier(ctx context.Context, view View, f GoFile, pos token.Pos) (*Ident
} }
path, _ := astutil.PathEnclosingInterval(file, pos, pos) path, _ := astutil.PathEnclosingInterval(file, pos, pos)
if path == nil { if path == nil {
return nil, fmt.Errorf("can't find node enclosing position") return nil, errors.Errorf("can't find node enclosing position")
} }
result := &IdentifierInfo{ result := &IdentifierInfo{
File: f, File: f,
@ -118,7 +118,7 @@ func identifier(ctx context.Context, view View, f GoFile, pos token.Pos) (*Ident
result.decl.wasImplicit = true result.decl.wasImplicit = true
} else { } else {
// Probably a type error. // Probably a type error.
return nil, fmt.Errorf("no object for ident %v", result.Name) return nil, errors.Errorf("no object for ident %v", result.Name)
} }
} }
@ -126,7 +126,7 @@ func identifier(ctx context.Context, view View, f GoFile, pos token.Pos) (*Ident
if result.decl.obj.Parent() == types.Universe { if result.decl.obj.Parent() == types.Universe {
decl, ok := lookupBuiltinDecl(f.View(), result.Name).(ast.Node) decl, ok := lookupBuiltinDecl(f.View(), result.Name).(ast.Node)
if !ok { if !ok {
return nil, fmt.Errorf("no declaration for %s", result.Name) return nil, errors.Errorf("no declaration for %s", result.Name)
} }
result.decl.node = decl result.decl.node = decl
if result.decl.rng, err = posToRange(ctx, f.FileSet(), result.Name, decl.Pos()); err != nil { if result.decl.rng, err = posToRange(ctx, f.FileSet(), result.Name, decl.Pos()); err != nil {
@ -214,7 +214,7 @@ func objToRange(ctx context.Context, fset *token.FileSet, obj types.Object) (spa
func posToRange(ctx context.Context, fset *token.FileSet, name string, pos token.Pos) (span.Range, error) { func posToRange(ctx context.Context, fset *token.FileSet, name string, pos token.Pos) (span.Range, error) {
if !pos.IsValid() { if !pos.IsValid() {
return span.Range{}, fmt.Errorf("invalid position for %v", name) return span.Range{}, errors.Errorf("invalid position for %v", name)
} }
return span.NewRange(fset, pos, pos+token.Pos(len(name))), nil return span.NewRange(fset, pos, pos+token.Pos(len(name))), nil
} }
@ -230,7 +230,7 @@ func objToNode(ctx context.Context, view View, originPkg *types.Package, obj typ
} }
declFile, ok := f.(GoFile) declFile, ok := f.(GoFile)
if !ok { if !ok {
return nil, fmt.Errorf("%s is not a Go file", s.URI()) return nil, errors.Errorf("%s is not a Go file", s.URI())
} }
// If the object is exported from a different package, // If the object is exported from a different package,
// we don't need its full AST to find the definition. // we don't need its full AST to find the definition.
@ -244,7 +244,7 @@ func objToNode(ctx context.Context, view View, originPkg *types.Package, obj typ
} }
path, _ := astutil.PathEnclosingInterval(declAST, rng.Start, rng.End) path, _ := astutil.PathEnclosingInterval(declAST, rng.Start, rng.End)
if path == nil { if path == nil {
return nil, fmt.Errorf("no path for range %v", rng) return nil, errors.Errorf("no path for range %v", rng)
} }
for _, node := range path { for _, node := range path {
switch node := node.(type) { switch node := node.(type) {
@ -277,7 +277,7 @@ func importSpec(ctx context.Context, f GoFile, fAST *ast.File, pkg Package, pos
} }
importPath, err := strconv.Unquote(imp.Path.Value) importPath, err := strconv.Unquote(imp.Path.Value)
if err != nil { if err != nil {
return nil, fmt.Errorf("import path not quoted: %s (%v)", imp.Path.Value, err) return nil, errors.Errorf("import path not quoted: %s (%v)", imp.Path.Value, err)
} }
result := &IdentifierInfo{ result := &IdentifierInfo{
File: f, File: f,
@ -288,10 +288,10 @@ func importSpec(ctx context.Context, f GoFile, fAST *ast.File, pkg Package, pos
// Consider the "declaration" of an import spec to be the imported package. // Consider the "declaration" of an import spec to be the imported package.
importedPkg := pkg.GetImport(importPath) importedPkg := pkg.GetImport(importPath)
if importedPkg == nil { if importedPkg == nil {
return nil, fmt.Errorf("no import for %q", importPath) return nil, errors.Errorf("no import for %q", importPath)
} }
if importedPkg.GetSyntax(ctx) == nil { if importedPkg.GetSyntax(ctx) == nil {
return nil, fmt.Errorf("no syntax for for %q", importPath) return nil, errors.Errorf("no syntax for for %q", importPath)
} }
// Heuristic: Jump to the longest (most "interesting") file of the package. // Heuristic: Jump to the longest (most "interesting") file of the package.
var dest *ast.File var dest *ast.File
@ -301,7 +301,7 @@ func importSpec(ctx context.Context, f GoFile, fAST *ast.File, pkg Package, pos
} }
} }
if dest == nil { if dest == nil {
return nil, fmt.Errorf("package %q has no files", importPath) return nil, errors.Errorf("package %q has no files", importPath)
} }
result.decl.rng = span.NewRange(f.FileSet(), dest.Name.Pos(), dest.Name.End()) result.decl.rng = span.NewRange(f.FileSet(), dest.Name.Pos(), dest.Name.End())
result.decl.node = imp result.decl.node = imp

View File

@ -6,12 +6,12 @@ package source
import ( import (
"context" "context"
"fmt"
"go/ast" "go/ast"
"go/types" "go/types"
"golang.org/x/tools/internal/lsp/telemetry/trace" "golang.org/x/tools/internal/lsp/telemetry/trace"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
errors "golang.org/x/xerrors"
) )
// ReferenceInfo holds information about reference to an identifier in Go source. // ReferenceInfo holds information about reference to an identifier in Go source.
@ -33,17 +33,17 @@ func (i *IdentifierInfo) References(ctx context.Context) ([]*ReferenceInfo, erro
// If the object declaration is nil, assume it is an import spec and do not look for references. // If the object declaration is nil, assume it is an import spec and do not look for references.
if i.decl.obj == nil { if i.decl.obj == nil {
return nil, fmt.Errorf("no references for an import spec") return nil, errors.Errorf("no references for an import spec")
} }
pkgs := i.File.GetPackages(ctx) pkgs := i.File.GetPackages(ctx)
for _, pkg := range pkgs { for _, pkg := range pkgs {
if pkg == nil || pkg.IsIllTyped() { if pkg == nil || pkg.IsIllTyped() {
return nil, fmt.Errorf("package for %s is ill typed", i.File.URI()) return nil, errors.Errorf("package for %s is ill typed", i.File.URI())
} }
info := pkg.GetTypesInfo() info := pkg.GetTypesInfo()
if info == nil { if info == nil {
return nil, fmt.Errorf("package %s has no types info", pkg.PkgPath()) return nil, errors.Errorf("package %s has no types info", pkg.PkgPath())
} }
if i.decl.wasImplicit { if i.decl.wasImplicit {

View File

@ -7,7 +7,6 @@ package source
import ( import (
"bytes" "bytes"
"context" "context"
"fmt"
"go/ast" "go/ast"
"go/format" "go/format"
"go/token" "go/token"
@ -18,6 +17,7 @@ import (
"golang.org/x/tools/internal/lsp/telemetry/trace" "golang.org/x/tools/internal/lsp/telemetry/trace"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
"golang.org/x/tools/refactor/satisfy" "golang.org/x/tools/refactor/satisfy"
errors "golang.org/x/xerrors"
) )
type renamer struct { type renamer struct {
@ -41,22 +41,22 @@ func (i *IdentifierInfo) Rename(ctx context.Context, newName string) (map[span.U
defer done() defer done()
if i.Name == newName { if i.Name == newName {
return nil, fmt.Errorf("old and new names are the same: %s", newName) return nil, errors.Errorf("old and new names are the same: %s", newName)
} }
if !isValidIdentifier(i.Name) { if !isValidIdentifier(i.Name) {
return nil, fmt.Errorf("invalid identifier to rename: %q", i.Name) return nil, errors.Errorf("invalid identifier to rename: %q", i.Name)
} }
if i.pkg == nil || i.pkg.IsIllTyped() { if i.pkg == nil || i.pkg.IsIllTyped() {
return nil, fmt.Errorf("package for %s is ill typed", i.File.URI()) return nil, errors.Errorf("package for %s is ill typed", i.File.URI())
} }
// Do not rename builtin identifiers. // Do not rename builtin identifiers.
if i.decl.obj.Parent() == types.Universe { if i.decl.obj.Parent() == types.Universe {
return nil, fmt.Errorf("cannot rename builtin %q", i.Name) return nil, errors.Errorf("cannot rename builtin %q", i.Name)
} }
// Do not rename identifiers declared in another package. // Do not rename identifiers declared in another package.
if i.pkg.GetTypes() != i.decl.obj.Pkg() { if i.pkg.GetTypes() != i.decl.obj.Pkg() {
return nil, fmt.Errorf("failed to rename because %q is declared in package %q", i.Name, i.decl.obj.Pkg().Name()) return nil, errors.Errorf("failed to rename because %q is declared in package %q", i.Name, i.decl.obj.Pkg().Name())
} }
refs, err := i.References(ctx) refs, err := i.References(ctx)
@ -83,7 +83,7 @@ func (i *IdentifierInfo) Rename(ctx context.Context, newName string) (map[span.U
r.check(from.obj) r.check(from.obj)
} }
if r.hadConflicts { if r.hadConflicts {
return nil, fmt.Errorf(r.errors) return nil, errors.Errorf(r.errors)
} }
changes, err := r.update() changes, err := r.update()
@ -200,11 +200,11 @@ func (r *renamer) updatePkgName(pkgName *types.PkgName) (*TextEdit, error) {
_, path, _ := pathEnclosingInterval(r.ctx, r.fset, pkg, pkgName.Pos(), pkgName.Pos()) _, path, _ := pathEnclosingInterval(r.ctx, r.fset, pkg, pkgName.Pos(), pkgName.Pos())
if len(path) < 2 { if len(path) < 2 {
return nil, fmt.Errorf("failed to update PkgName for %s", pkgName.Name()) return nil, errors.Errorf("failed to update PkgName for %s", pkgName.Name())
} }
spec, ok := path[1].(*ast.ImportSpec) spec, ok := path[1].(*ast.ImportSpec)
if !ok { if !ok {
return nil, fmt.Errorf("failed to update PkgName for %s", pkgName.Name()) return nil, errors.Errorf("failed to update PkgName for %s", pkgName.Name())
} }
var astIdent *ast.Ident // will be nil if ident is removed var astIdent *ast.Ident // will be nil if ident is removed

View File

@ -6,13 +6,13 @@ package source
import ( import (
"context" "context"
"fmt"
"go/ast" "go/ast"
"go/token" "go/token"
"go/types" "go/types"
"golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/go/ast/astutil"
"golang.org/x/tools/internal/lsp/telemetry/trace" "golang.org/x/tools/internal/lsp/telemetry/trace"
errors "golang.org/x/xerrors"
) )
type SignatureInformation struct { type SignatureInformation struct {
@ -35,14 +35,14 @@ func SignatureHelp(ctx context.Context, f GoFile, pos token.Pos) (*SignatureInfo
} }
pkg := f.GetPackage(ctx) pkg := f.GetPackage(ctx)
if pkg == nil || pkg.IsIllTyped() { if pkg == nil || pkg.IsIllTyped() {
return nil, fmt.Errorf("package for %s is ill typed", f.URI()) return nil, errors.Errorf("package for %s is ill typed", f.URI())
} }
// Find a call expression surrounding the query position. // Find a call expression surrounding the query position.
var callExpr *ast.CallExpr var callExpr *ast.CallExpr
path, _ := astutil.PathEnclosingInterval(file, pos, pos) path, _ := astutil.PathEnclosingInterval(file, pos, pos)
if path == nil { if path == nil {
return nil, fmt.Errorf("cannot find node enclosing position") return nil, errors.Errorf("cannot find node enclosing position")
} }
FindCall: FindCall:
for _, node := range path { for _, node := range path {
@ -56,11 +56,11 @@ FindCall:
// The user is within an anonymous function, // The user is within an anonymous function,
// which may be the parameter to the *ast.CallExpr. // which may be the parameter to the *ast.CallExpr.
// Don't show signature help in this case. // Don't show signature help in this case.
return nil, fmt.Errorf("no signature help within a function declaration") return nil, errors.Errorf("no signature help within a function declaration")
} }
} }
if callExpr == nil || callExpr.Fun == nil { if callExpr == nil || callExpr.Fun == nil {
return nil, fmt.Errorf("cannot find an enclosing function") return nil, errors.Errorf("cannot find an enclosing function")
} }
// Get the object representing the function, if available. // Get the object representing the function, if available.
@ -82,12 +82,12 @@ FindCall:
// Get the type information for the function being called. // Get the type information for the function being called.
sigType := pkg.GetTypesInfo().TypeOf(callExpr.Fun) sigType := pkg.GetTypesInfo().TypeOf(callExpr.Fun)
if sigType == nil { if sigType == nil {
return nil, fmt.Errorf("cannot get type for Fun %[1]T (%[1]v)", callExpr.Fun) return nil, errors.Errorf("cannot get type for Fun %[1]T (%[1]v)", callExpr.Fun)
} }
sig, _ := sigType.Underlying().(*types.Signature) sig, _ := sigType.Underlying().(*types.Signature)
if sig == nil { if sig == nil {
return nil, fmt.Errorf("cannot find signature for Fun %[1]T (%[1]v)", callExpr.Fun) return nil, errors.Errorf("cannot find signature for Fun %[1]T (%[1]v)", callExpr.Fun)
} }
qf := qualifier(file, pkg.GetTypes(), pkg.GetTypesInfo()) qf := qualifier(file, pkg.GetTypes(), pkg.GetTypesInfo())
@ -128,7 +128,7 @@ FindCall:
func builtinSignature(ctx context.Context, v View, callExpr *ast.CallExpr, name string, pos token.Pos) (*SignatureInformation, error) { func builtinSignature(ctx context.Context, v View, callExpr *ast.CallExpr, name string, pos token.Pos) (*SignatureInformation, error) {
decl, ok := lookupBuiltinDecl(v, name).(*ast.FuncDecl) decl, ok := lookupBuiltinDecl(v, name).(*ast.FuncDecl)
if !ok { if !ok {
return nil, fmt.Errorf("no function declaration for builtin: %s", name) return nil, errors.Errorf("no function declaration for builtin: %s", name)
} }
params, _ := formatFieldList(ctx, v, decl.Type.Params) params, _ := formatFieldList(ctx, v, decl.Type.Params)
results, writeResultParens := formatFieldList(ctx, v, decl.Type.Results) results, writeResultParens := formatFieldList(ctx, v, decl.Type.Results)

View File

@ -6,7 +6,6 @@ package source
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"go/ast" "go/ast"
"go/token" "go/token"
@ -14,6 +13,7 @@ import (
"golang.org/x/tools/internal/lsp/telemetry/trace" "golang.org/x/tools/internal/lsp/telemetry/trace"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
errors "golang.org/x/xerrors"
) )
type SymbolKind int type SymbolKind int
@ -52,7 +52,7 @@ func DocumentSymbols(ctx context.Context, f GoFile) ([]Symbol, error) {
} }
pkg := f.GetPackage(ctx) pkg := f.GetPackage(ctx)
if pkg == nil || pkg.IsIllTyped() { if pkg == nil || pkg.IsIllTyped() {
return nil, fmt.Errorf("no package for %s", f.URI()) return nil, errors.Errorf("no package for %s", f.URI())
} }
info := pkg.GetTypesInfo() info := pkg.GetTypesInfo()
q := qualifier(file, pkg.GetTypes(), info) q := qualifier(file, pkg.GetTypes(), info)

View File

@ -7,7 +7,6 @@ package lsp
import ( import (
"bytes" "bytes"
"context" "context"
"fmt"
"golang.org/x/tools/internal/jsonrpc2" "golang.org/x/tools/internal/jsonrpc2"
"golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/protocol"
@ -16,6 +15,7 @@ import (
"golang.org/x/tools/internal/lsp/telemetry/log" "golang.org/x/tools/internal/lsp/telemetry/log"
"golang.org/x/tools/internal/lsp/telemetry/trace" "golang.org/x/tools/internal/lsp/telemetry/trace"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
errors "golang.org/x/xerrors"
) )
func (s *Server) didOpen(ctx context.Context, params *protocol.DidOpenTextDocumentParams) error { func (s *Server) didOpen(ctx context.Context, params *protocol.DidOpenTextDocumentParams) error {
@ -54,7 +54,7 @@ func (s *Server) didChange(ctx context.Context, params *protocol.DidChangeTextDo
if !isFullChange { if !isFullChange {
switch s.textDocumentSyncKind { switch s.textDocumentSyncKind {
case protocol.Full: case protocol.Full:
return fmt.Errorf("expected a full content change, received incremental changes for %s", uri) return errors.Errorf("expected a full content change, received incremental changes for %s", uri)
case protocol.Incremental: case protocol.Incremental:
// Determine the new file content. // Determine the new file content.
var err error var err error

View File

@ -6,11 +6,11 @@ package lsp
import ( import (
"context" "context"
"fmt"
"golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/protocol"
"golang.org/x/tools/internal/lsp/source" "golang.org/x/tools/internal/lsp/source"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
errors "golang.org/x/xerrors"
) )
func getSourceFile(ctx context.Context, v source.View, uri span.URI) (source.File, *protocol.ColumnMapper, error) { func getSourceFile(ctx context.Context, v source.View, uri span.URI) (source.File, *protocol.ColumnMapper, error) {
@ -38,7 +38,7 @@ func getGoFile(ctx context.Context, v source.View, uri span.URI) (source.GoFile,
} }
gof, ok := f.(source.GoFile) gof, ok := f.(source.GoFile)
if !ok { if !ok {
return nil, nil, fmt.Errorf("not a Go file %v", f.URI()) return nil, nil, errors.Errorf("not a Go file %v", f.URI())
} }
return gof, m, nil return gof, m, nil
} }

View File

@ -6,10 +6,10 @@ package lsp
import ( import (
"context" "context"
"fmt"
"golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/protocol"
"golang.org/x/tools/internal/span" "golang.org/x/tools/internal/span"
errors "golang.org/x/xerrors"
) )
func (s *Server) changeFolders(ctx context.Context, event protocol.WorkspaceFoldersChangeEvent) error { func (s *Server) changeFolders(ctx context.Context, event protocol.WorkspaceFoldersChangeEvent) error {
@ -18,7 +18,7 @@ func (s *Server) changeFolders(ctx context.Context, event protocol.WorkspaceFold
if view != nil { if view != nil {
view.Shutdown(ctx) view.Shutdown(ctx)
} else { } else {
return fmt.Errorf("view %s for %v not found", folder.Name, folder.URI) return errors.Errorf("view %s for %v not found", folder.Name, folder.URI)
} }
} }