internal/lsp: add more error handling to analysis
Updates golang/go#30786 Change-Id: Icf054b9bcd62b36e3aa55288946a9f0d1c845300 Reviewed-on: https://go-review.googlesource.com/c/tools/+/172972 Run-TryBot: Rebecca Stambler <rstambler@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Cottrell <iancottrell@google.com>
This commit is contained in:
parent
3ff669b183
commit
c6b416e8a4
|
@ -18,17 +18,22 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
)
|
)
|
||||||
|
|
||||||
func analyze(ctx context.Context, v View, pkgs []Package, analyzers []*analysis.Analyzer) []*Action {
|
func analyze(ctx context.Context, v View, pkgs []Package, analyzers []*analysis.Analyzer) ([]*Action, error) {
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return nil, ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
// Build nodes for initial packages.
|
// Build nodes for initial packages.
|
||||||
var roots []*Action
|
var roots []*Action
|
||||||
for _, a := range analyzers {
|
for _, a := range analyzers {
|
||||||
for _, pkg := range pkgs {
|
for _, pkg := range pkgs {
|
||||||
root, err := pkg.GetActionGraph(ctx, a)
|
root, err := pkg.GetActionGraph(ctx, a)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
return nil, err
|
||||||
}
|
}
|
||||||
root.isroot = true
|
root.isroot = true
|
||||||
roots = append(roots, root)
|
roots = append(roots, root)
|
||||||
|
@ -36,9 +41,9 @@ func analyze(ctx context.Context, v View, pkgs []Package, analyzers []*analysis.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the graph in parallel.
|
// Execute the graph in parallel.
|
||||||
execAll(v.FileSet(), roots)
|
execAll(ctx, v.FileSet(), roots)
|
||||||
|
|
||||||
return roots
|
return roots, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// An action represents one unit of analysis work: the application of
|
// An action represents one unit of analysis work: the application of
|
||||||
|
@ -75,28 +80,27 @@ func (act *Action) String() string {
|
||||||
return fmt.Sprintf("%s@%s", act.Analyzer, act.Pkg)
|
return fmt.Sprintf("%s@%s", act.Analyzer, act.Pkg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func execAll(fset *token.FileSet, actions []*Action) {
|
func execAll(ctx context.Context, fset *token.FileSet, actions []*Action) error {
|
||||||
var wg sync.WaitGroup
|
g, ctx := errgroup.WithContext(ctx)
|
||||||
for _, act := range actions {
|
for _, act := range actions {
|
||||||
wg.Add(1)
|
act := act
|
||||||
work := func(act *Action) {
|
g.Go(func() error {
|
||||||
act.exec(fset)
|
act.exec(ctx, fset)
|
||||||
wg.Done()
|
return nil
|
||||||
}
|
})
|
||||||
go work(act)
|
|
||||||
}
|
}
|
||||||
wg.Wait()
|
return g.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (act *Action) exec(fset *token.FileSet) {
|
func (act *Action) exec(ctx context.Context, fset *token.FileSet) {
|
||||||
act.once.Do(func() {
|
act.once.Do(func() {
|
||||||
act.execOnce(fset)
|
act.execOnce(ctx, fset)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (act *Action) execOnce(fset *token.FileSet) {
|
func (act *Action) execOnce(ctx context.Context, fset *token.FileSet) {
|
||||||
// Analyze dependencies.
|
// Analyze dependencies.
|
||||||
execAll(fset, act.Deps)
|
execAll(ctx, fset, act.Deps)
|
||||||
|
|
||||||
// Report an error if any dependency failed.
|
// Report an error if any dependency failed.
|
||||||
var failed []string
|
var failed []string
|
||||||
|
|
|
@ -101,13 +101,12 @@ func Diagnostics(ctx context.Context, v View, uri span.URI) (map[span.URI][]Diag
|
||||||
return reports, nil
|
return reports, nil
|
||||||
}
|
}
|
||||||
// Type checking and parsing succeeded. Run analyses.
|
// Type checking and parsing succeeded. Run analyses.
|
||||||
runAnalyses(ctx, v, pkg, func(a *analysis.Analyzer, diag analysis.Diagnostic) {
|
runAnalyses(ctx, v, pkg, func(a *analysis.Analyzer, diag analysis.Diagnostic) error {
|
||||||
r := span.NewRange(v.FileSet(), diag.Pos, 0)
|
r := span.NewRange(v.FileSet(), diag.Pos, 0)
|
||||||
s, err := r.Span()
|
s, err := r.Span()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//TODO: we could not process the diag.Pos, and thus have no valid span
|
// The diagnostic has an invalid position, so we don't have a valid span.
|
||||||
//we don't have anywhere to put this error though
|
return err
|
||||||
v.Logger().Errorf(ctx, "%v", err)
|
|
||||||
}
|
}
|
||||||
category := a.Name
|
category := a.Name
|
||||||
if diag.Category != "" {
|
if diag.Category != "" {
|
||||||
|
@ -119,6 +118,7 @@ func Diagnostics(ctx context.Context, v View, uri span.URI) (map[span.URI][]Diag
|
||||||
Message: diag.Message,
|
Message: diag.Message,
|
||||||
Severity: SeverityWarning,
|
Severity: SeverityWarning,
|
||||||
})
|
})
|
||||||
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
return reports, nil
|
return reports, nil
|
||||||
|
@ -168,8 +168,8 @@ func singleDiagnostic(uri span.URI, format string, a ...interface{}) map[span.UR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func runAnalyses(ctx context.Context, v View, pkg Package, report func(a *analysis.Analyzer, diag analysis.Diagnostic)) error {
|
func runAnalyses(ctx context.Context, v View, pkg Package, report func(a *analysis.Analyzer, diag analysis.Diagnostic) error) error {
|
||||||
// the traditional vet suite:
|
// The traditional vet suite:
|
||||||
analyzers := []*analysis.Analyzer{
|
analyzers := []*analysis.Analyzer{
|
||||||
asmdecl.Analyzer,
|
asmdecl.Analyzer,
|
||||||
assign.Analyzer,
|
assign.Analyzer,
|
||||||
|
@ -195,7 +195,10 @@ func runAnalyses(ctx context.Context, v View, pkg Package, report func(a *analys
|
||||||
unusedresult.Analyzer,
|
unusedresult.Analyzer,
|
||||||
}
|
}
|
||||||
|
|
||||||
roots := analyze(ctx, v, []Package{pkg}, analyzers)
|
roots, err := analyze(ctx, v, []Package{pkg}, analyzers)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Report diagnostics and errors from root analyzers.
|
// Report diagnostics and errors from root analyzers.
|
||||||
for _, r := range roots {
|
for _, r := range roots {
|
||||||
|
@ -205,9 +208,10 @@ func runAnalyses(ctx context.Context, v View, pkg Package, report func(a *analys
|
||||||
// which isn't super useful...
|
// which isn't super useful...
|
||||||
return r.err
|
return r.err
|
||||||
}
|
}
|
||||||
report(r.Analyzer, diag)
|
if err := report(r.Analyzer, diag); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue