internal/lsp: add an error result to findFile
This change allows us to return diagnostics in the case of a file that doesn't exist. Change-Id: I6275c0dc9103a3f44070919937afe27c64545828 Reviewed-on: https://go-review.googlesource.com/c/tools/+/170009 Reviewed-by: Ian Cottrell <iancottrell@google.com> Run-TryBot: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
parent
0ec5c269d4
commit
24738cbdc1
|
@ -150,7 +150,7 @@ func (v *View) link(pkgPath string, pkg *packages.Package, parent *metadata) *me
|
|||
m.name = pkg.Name
|
||||
m.files = pkg.CompiledGoFiles
|
||||
for _, filename := range m.files {
|
||||
if f := v.findFile(span.FileURI(filename)); f != nil {
|
||||
if f, _ := v.findFile(span.FileURI(filename)); f != nil {
|
||||
f.meta = m
|
||||
}
|
||||
}
|
||||
|
@ -341,7 +341,10 @@ func (v *View) parseFiles(filenames []string) ([]*ast.File, []error) {
|
|||
}
|
||||
|
||||
// First, check if we have already cached an AST for this file.
|
||||
f := v.findFile(span.FileURI(filename))
|
||||
f, err := v.findFile(span.FileURI(filename))
|
||||
if err != nil {
|
||||
parsed[i], errors[i] = nil, err
|
||||
}
|
||||
var fAST *ast.File
|
||||
if f != nil {
|
||||
fAST = f.ast
|
||||
|
|
|
@ -191,7 +191,7 @@ func (v *View) remove(pkgPath string) {
|
|||
// All of the files in the package may also be holding a pointer to the
|
||||
// invalidated package.
|
||||
for _, filename := range m.files {
|
||||
if f := v.findFile(span.FileURI(filename)); f != nil {
|
||||
if f, _ := v.findFile(span.FileURI(filename)); f != nil {
|
||||
f.pkg = nil
|
||||
}
|
||||
}
|
||||
|
@ -213,7 +213,9 @@ func (v *View) GetFile(ctx context.Context, uri span.URI) (source.File, error) {
|
|||
|
||||
// getFile is the unlocked internal implementation of GetFile.
|
||||
func (v *View) getFile(uri span.URI) (*File, error) {
|
||||
if f := v.findFile(uri); f != nil {
|
||||
if f, err := v.findFile(uri); err != nil {
|
||||
return nil, err
|
||||
} else if f != nil {
|
||||
return f, nil
|
||||
}
|
||||
filename, err := uri.Filename()
|
||||
|
@ -228,34 +230,41 @@ func (v *View) getFile(uri span.URI) (*File, error) {
|
|||
return f, nil
|
||||
}
|
||||
|
||||
func (v *View) findFile(uri span.URI) *File {
|
||||
// findFile checks the cache for any file matching the given uri.
|
||||
//
|
||||
// An error is only returned for an irreparable failure, for example, if the
|
||||
// filename in question does not exist.
|
||||
func (v *View) findFile(uri span.URI) (*File, error) {
|
||||
if f := v.filesByURI[uri]; f != nil {
|
||||
// a perfect match
|
||||
return f
|
||||
return f, nil
|
||||
}
|
||||
// no exact match stored, time to do some real work
|
||||
// check for any files with the same basename
|
||||
fname, err := uri.Filename()
|
||||
if err != nil {
|
||||
return nil
|
||||
return nil, err
|
||||
}
|
||||
basename := basename(fname)
|
||||
if candidates := v.filesByBase[basename]; candidates != nil {
|
||||
pathStat, err := os.Stat(fname)
|
||||
if err != nil {
|
||||
return nil
|
||||
if os.IsNotExist(err) {
|
||||
return nil, err
|
||||
} else if err != nil {
|
||||
return nil, nil // the file may exist, return without an error
|
||||
}
|
||||
for _, c := range candidates {
|
||||
if cStat, err := os.Stat(c.filename); err == nil {
|
||||
if os.SameFile(pathStat, cStat) {
|
||||
// same file, map it
|
||||
v.mapFile(uri, c)
|
||||
return c
|
||||
return c, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
// no file with a matching name was found, it wasn't in our cache
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (v *View) mapFile(uri span.URI, f *File) {
|
||||
|
|
|
@ -54,18 +54,11 @@ const (
|
|||
func Diagnostics(ctx context.Context, v View, uri span.URI) (map[span.URI][]Diagnostic, error) {
|
||||
f, err := v.GetFile(ctx, uri)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return singleDiagnostic(uri, "no file found for %s", uri), nil
|
||||
}
|
||||
pkg := f.GetPackage(ctx)
|
||||
if pkg == nil {
|
||||
return map[span.URI][]Diagnostic{
|
||||
uri: []Diagnostic{{
|
||||
Source: "LSP",
|
||||
Span: span.New(uri, span.Point{}, span.Point{}),
|
||||
Message: fmt.Sprintf("not part of a package"),
|
||||
Severity: SeverityError,
|
||||
}},
|
||||
}, nil
|
||||
return singleDiagnostic(uri, "%s is not part of a package", uri), nil
|
||||
}
|
||||
// Prepare the reports we will send for this package.
|
||||
reports := make(map[span.URI][]Diagnostic)
|
||||
|
@ -149,6 +142,17 @@ func Diagnostics(ctx context.Context, v View, uri span.URI) (map[span.URI][]Diag
|
|||
return reports, nil
|
||||
}
|
||||
|
||||
func singleDiagnostic(uri span.URI, format string, a ...interface{}) map[span.URI][]Diagnostic {
|
||||
return map[span.URI][]Diagnostic{
|
||||
uri: []Diagnostic{{
|
||||
Source: "LSP",
|
||||
Span: span.New(uri, span.Point{}, span.Point{}),
|
||||
Message: fmt.Sprintf(format, a...),
|
||||
Severity: SeverityError,
|
||||
}},
|
||||
}
|
||||
}
|
||||
|
||||
func runAnalyses(ctx context.Context, v View, pkg Package, report func(a *analysis.Analyzer, diag analysis.Diagnostic)) error {
|
||||
// the traditional vet suite:
|
||||
analyzers := []*analysis.Analyzer{
|
||||
|
|
Loading…
Reference in New Issue