mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
internal/lsp/cache: recover from panics in analyses
Some analyses may panic, so we should be careful to recover. Change-Id: Ie13df07aca1a21f4e6a66648cd4890b6a31966cc Reviewed-on: https://go-review.googlesource.com/c/tools/+/204817 Run-TryBot: Rebecca Stambler <rstambler@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Michael Matloob <matloob@golang.org>
This commit is contained in:
parent
a860bcda08
commit
8dbcdeb83d
43
internal/lsp/cache/analysis.go
vendored
43
internal/lsp/cache/analysis.go
vendored
@ -12,6 +12,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/source"
|
"golang.org/x/tools/internal/lsp/source"
|
||||||
|
"golang.org/x/tools/internal/lsp/telemetry"
|
||||||
"golang.org/x/tools/internal/memoize"
|
"golang.org/x/tools/internal/memoize"
|
||||||
"golang.org/x/tools/internal/telemetry/log"
|
"golang.org/x/tools/internal/telemetry/log"
|
||||||
errors "golang.org/x/xerrors"
|
errors "golang.org/x/xerrors"
|
||||||
@ -123,14 +124,14 @@ func (s *snapshot) actionHandle(ctx context.Context, id packageID, mode source.P
|
|||||||
fset := s.view.session.cache.fset
|
fset := s.view.session.cache.fset
|
||||||
|
|
||||||
h := s.view.session.cache.store.Bind(buildActionKey(a, cph), func(ctx context.Context) interface{} {
|
h := s.view.session.cache.store.Bind(buildActionKey(a, cph), func(ctx context.Context) interface{} {
|
||||||
data := &actionData{}
|
// Analyze dependencies first.
|
||||||
// Analyze dependencies.
|
|
||||||
results, err := execAll(ctx, fset, deps)
|
results, err := execAll(ctx, fset, deps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
data.err = err
|
return &actionData{
|
||||||
return nil
|
err: err,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
data.diagnostics, data.result, data.objectFacts, data.packageFacts, data.err = runAnalysis(ctx, fset, a, pkg, results)
|
data := runAnalysis(ctx, fset, a, pkg, results)
|
||||||
return data
|
return data
|
||||||
})
|
})
|
||||||
ah.handle = h
|
ah.handle = h
|
||||||
@ -192,7 +193,18 @@ func execAll(ctx context.Context, fset *token.FileSet, actions []*actionHandle)
|
|||||||
return results, g.Wait()
|
return results, g.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func runAnalysis(ctx context.Context, fset *token.FileSet, analyzer *analysis.Analyzer, pkg *pkg, deps map[*actionHandle]*actionData) ([]*source.Error, interface{}, map[objectFactKey]analysis.Fact, map[packageFactKey]analysis.Fact, error) {
|
func runAnalysis(ctx context.Context, fset *token.FileSet, analyzer *analysis.Analyzer, pkg *pkg, deps map[*actionHandle]*actionData) (data *actionData) {
|
||||||
|
data = &actionData{
|
||||||
|
objectFacts: make(map[objectFactKey]analysis.Fact),
|
||||||
|
packageFacts: make(map[packageFactKey]analysis.Fact),
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
log.Print(ctx, fmt.Sprintf("analysis panicked: %s", r), telemetry.Package.Of(pkg.PkgPath))
|
||||||
|
data.err = errors.Errorf("analysis %s for package %s panicked: %v", analyzer.Name, pkg.PkgPath())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
// Plumb the output values of the dependencies
|
// Plumb the output values of the dependencies
|
||||||
// into the inputs of this action. Also facts.
|
// into the inputs of this action. Also facts.
|
||||||
inputs := make(map[*analysis.Analyzer]interface{})
|
inputs := make(map[*analysis.Analyzer]interface{})
|
||||||
@ -300,14 +312,16 @@ func runAnalysis(ctx context.Context, fset *token.FileSet, analyzer *analysis.An
|
|||||||
}
|
}
|
||||||
|
|
||||||
if pkg.IsIllTyped() {
|
if pkg.IsIllTyped() {
|
||||||
return nil, nil, nil, nil, errors.Errorf("analysis skipped due to errors in package: %v", pkg.GetErrors())
|
data.err = errors.Errorf("analysis skipped due to errors in package: %v", pkg.GetErrors())
|
||||||
|
return data
|
||||||
}
|
}
|
||||||
result, err := pass.Analyzer.Run(pass)
|
data.result, data.err = pass.Analyzer.Run(pass)
|
||||||
if err == nil {
|
if data.err == nil {
|
||||||
if got, want := reflect.TypeOf(result), pass.Analyzer.ResultType; got != want {
|
if got, want := reflect.TypeOf(data.result), pass.Analyzer.ResultType; got != want {
|
||||||
err = errors.Errorf(
|
data.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)
|
||||||
|
return data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,15 +333,14 @@ func runAnalysis(ctx context.Context, fset *token.FileSet, analyzer *analysis.An
|
|||||||
panic(fmt.Sprintf("%s:%s: Pass.ExportPackageFact(%T) called after Run", analyzer.Name, pkg.PkgPath(), fact))
|
panic(fmt.Sprintf("%s:%s: Pass.ExportPackageFact(%T) called after Run", analyzer.Name, pkg.PkgPath(), fact))
|
||||||
}
|
}
|
||||||
|
|
||||||
var errors []*source.Error
|
|
||||||
for _, diag := range diagnostics {
|
for _, diag := range diagnostics {
|
||||||
srcErr, err := sourceError(ctx, fset, pkg, diag)
|
srcErr, err := sourceError(ctx, fset, pkg, diag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, err
|
return nil
|
||||||
}
|
}
|
||||||
errors = append(errors, srcErr)
|
data.diagnostics = append(data.diagnostics, srcErr)
|
||||||
}
|
}
|
||||||
return errors, result, objectFacts, packageFacts, err
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
// exportedFrom reports whether obj may be visible to a package that imports pkg.
|
// exportedFrom reports whether obj may be visible to a package that imports pkg.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user