1
0
mirror of https://github.com/golang/go synced 2024-11-05 15:06:09 -07:00

internal/lsp: move error range computations into cache package

A continuation of CL 202298, only for analysis errors.

Change-Id: I957d52cef31938ef66be73463e92695a5b56869c
Reviewed-on: https://go-review.googlesource.com/c/tools/+/202540
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:
Rebecca Stambler 2019-10-21 17:25:09 -04:00
parent d2fffb4b84
commit 3057e18543
8 changed files with 227 additions and 299 deletions

View File

@ -17,7 +17,7 @@ import (
errors "golang.org/x/xerrors"
)
func (s *snapshot) Analyze(ctx context.Context, id string, analyzers []*analysis.Analyzer) (map[*analysis.Analyzer][]*analysis.Diagnostic, error) {
func (s *snapshot) Analyze(ctx context.Context, id string, analyzers []*analysis.Analyzer) (map[*analysis.Analyzer][]*source.Error, error) {
var roots []*actionHandle
for _, a := range analyzers {
@ -34,7 +34,7 @@ func (s *snapshot) Analyze(ctx context.Context, id string, analyzers []*analysis
return nil, ctx.Err()
}
results := make(map[*analysis.Analyzer][]*analysis.Diagnostic)
results := make(map[*analysis.Analyzer][]*source.Error)
for _, ah := range roots {
diagnostics, _, err := ah.analyze(ctx)
if err != nil {
@ -63,7 +63,7 @@ type actionHandle struct {
}
type actionData struct {
diagnostics []*analysis.Diagnostic
diagnostics []*source.Error
result interface{}
err error
}
@ -133,7 +133,7 @@ func (s *snapshot) actionHandle(ctx context.Context, id packageID, mode source.P
return ah, nil
}
func (act *actionHandle) analyze(ctx context.Context) ([]*analysis.Diagnostic, interface{}, error) {
func (act *actionHandle) analyze(ctx context.Context) ([]*source.Error, interface{}, error) {
v := act.handle.Get(ctx)
if v == nil {
return nil, nil, errors.Errorf("no analyses for %s", act.pkg.ID())
@ -150,10 +150,10 @@ func (act *actionHandle) String() string {
return fmt.Sprintf("%s@%s", act.analyzer, act.pkg.PkgPath())
}
func execAll(ctx context.Context, fset *token.FileSet, actions []*actionHandle) (map[*actionHandle][]*analysis.Diagnostic, map[*actionHandle]interface{}, error) {
func execAll(ctx context.Context, fset *token.FileSet, actions []*actionHandle) (map[*actionHandle][]*source.Error, map[*actionHandle]interface{}, error) {
var (
mu sync.Mutex
diagnostics = make(map[*actionHandle][]*analysis.Diagnostic)
diagnostics = make(map[*actionHandle][]*source.Error)
results = make(map[*actionHandle]interface{})
)
@ -178,7 +178,7 @@ func execAll(ctx context.Context, fset *token.FileSet, actions []*actionHandle)
return diagnostics, results, g.Wait()
}
func (act *actionHandle) exec(ctx context.Context, fset *token.FileSet) (diagnostics []*analysis.Diagnostic, result interface{}, err error) {
func (act *actionHandle) exec(ctx context.Context, fset *token.FileSet) ([]*source.Error, interface{}, error) {
// Analyze dependencies.
_, depResults, err := execAll(ctx, fset, act.deps)
if err != nil {
@ -204,6 +204,8 @@ func (act *actionHandle) exec(ctx context.Context, fset *token.FileSet) (diagnos
}
}
var diagnostics []*analysis.Diagnostic
// Run the analysis.
pass := &analysis.Pass{
Analyzer: act.analyzer,
@ -225,14 +227,13 @@ func (act *actionHandle) exec(ctx context.Context, fset *token.FileSet) (diagnos
if act.pkg.IsIllTyped() {
return nil, nil, errors.Errorf("analysis skipped due to errors in package: %v", act.pkg.GetErrors())
} else {
result, err = pass.Analyzer.Run(pass)
if err == nil {
if got, want := reflect.TypeOf(result), pass.Analyzer.ResultType; got != want {
err = errors.Errorf(
"internal error: on package %s, analyzer %s returned a result of type %v, but declared ResultType %v",
pass.Pkg.Path(), pass.Analyzer, got, want)
}
}
result, err := pass.Analyzer.Run(pass)
if err == nil {
if got, want := reflect.TypeOf(result), pass.Analyzer.ResultType; got != want {
err = errors.Errorf(
"internal error: on package %s, analyzer %s returned a result of type %v, but declared ResultType %v",
pass.Pkg.Path(), pass.Analyzer, got, want)
}
}
@ -240,7 +241,15 @@ func (act *actionHandle) exec(ctx context.Context, fset *token.FileSet) (diagnos
pass.ExportObjectFact = nil
pass.ExportPackageFact = nil
return diagnostics, result, err
var errors []*source.Error
for _, diag := range diagnostics {
srcErr, err := sourceError(ctx, act.pkg, diag)
if err != nil {
return nil, nil, err
}
errors = append(errors, srcErr)
}
return errors, result, err
}
// inheritFacts populates act.facts with

View File

@ -337,11 +337,11 @@ func (imp *importer) typeCheck(ctx context.Context, cph *checkPackageHandle) (*p
_ = check.Files(files)
for _, e := range rawErrors {
srcErr, err := sourceError(ctx, imp.snapshot.view, pkg, e)
srcErr, err := sourceError(ctx, pkg, e)
if err != nil {
return nil, err
}
pkg.errors = append(pkg.errors, *srcErr)
pkg.errors = append(pkg.errors, srcErr)
}
return pkg, nil

View File

@ -7,17 +7,21 @@ import (
"go/types"
"strings"
"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"
)
func sourceError(ctx context.Context, view *view, pkg *pkg, e error) (*source.Error, error) {
func sourceError(ctx context.Context, pkg *pkg, e interface{}) (*source.Error, error) {
var (
spn span.Span
msg string
kind packages.ErrorKind
spn span.Span
err error
msg, category string
kind source.ErrorKind
fixes []source.SuggestedFix
related []source.RelatedInformation
)
switch e := e.(type) {
case packages.Error:
@ -27,35 +31,113 @@ func sourceError(ctx context.Context, view *view, pkg *pkg, e error) (*source.Er
spn = span.Parse(e.Pos)
}
msg = e.Msg
kind = e.Kind
kind = toSourceErrorKind(e.Kind)
case *scanner.Error:
msg = e.Msg
kind = packages.ParseError
kind = source.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
kind = source.ParseError
}
case types.Error:
spn = span.Parse(view.session.cache.fset.Position(e.Pos).String())
spn = span.Parse(pkg.snapshot.view.session.cache.fset.Position(e.Pos).String())
msg = e.Msg
kind = packages.TypeError
kind = source.TypeError
case *analysis.Diagnostic:
spn, err = span.NewRange(pkg.snapshot.view.session.cache.fset, e.Pos, e.End).Span()
if err != nil {
return nil, err
}
msg = e.Message
kind = source.Analysis
category = e.Category
fixes, err = suggestedFixes(ctx, pkg, e)
if err != nil {
return nil, err
}
related, err = relatedInformation(ctx, pkg, e)
if err != nil {
return nil, err
}
}
rng, err := spanToRange(ctx, pkg, spn, kind == packages.TypeError)
rng, err := spanToRange(ctx, pkg, spn, kind == source.TypeError)
if err != nil {
return nil, err
}
return &source.Error{
URI: spn.URI(),
Range: rng,
Msg: msg,
Kind: kind,
URI: spn.URI(),
Range: rng,
Message: msg,
Kind: kind,
Category: category,
SuggestedFixes: fixes,
Related: related,
}, nil
}
func suggestedFixes(ctx context.Context, pkg *pkg, diag *analysis.Diagnostic) ([]source.SuggestedFix, error) {
var fixes []source.SuggestedFix
for _, fix := range diag.SuggestedFixes {
edits := make(map[span.URI][]protocol.TextEdit)
for _, e := range fix.TextEdits {
spn, err := span.NewRange(pkg.Snapshot().View().Session().Cache().FileSet(), e.Pos, e.End).Span()
if err != nil {
return nil, err
}
rng, err := spanToRange(ctx, pkg, spn, false)
if err != nil {
return nil, err
}
edits[spn.URI()] = append(edits[spn.URI()], protocol.TextEdit{
Range: rng,
NewText: string(e.NewText),
})
}
fixes = append(fixes, source.SuggestedFix{
Title: fix.Message,
Edits: edits,
})
}
return fixes, nil
}
func relatedInformation(ctx context.Context, pkg *pkg, diag *analysis.Diagnostic) ([]source.RelatedInformation, error) {
var out []source.RelatedInformation
for _, related := range diag.Related {
spn, err := span.NewRange(pkg.Snapshot().View().Session().Cache().FileSet(), related.Pos, related.End).Span()
if err != nil {
return nil, err
}
rng, err := spanToRange(ctx, pkg, spn, false)
if err != nil {
return nil, err
}
out = append(out, source.RelatedInformation{
URI: spn.URI(),
Range: rng,
Message: related.Message,
})
}
return out, nil
}
func toSourceErrorKind(kind packages.ErrorKind) source.ErrorKind {
switch kind {
case packages.ListError:
return source.ListError
case packages.ParseError:
return source.ParseError
case packages.TypeError:
return source.TypeError
default:
return source.UnknownError
}
}
// 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) {
@ -67,11 +149,11 @@ func spanToRange(ctx context.Context, pkg *pkg, spn span.Span, isTypeError bool)
if err != nil {
return protocol.Range{}, err
}
data, _, err := ph.File().Read(ctx)
if err != nil {
return protocol.Range{}, err
}
if spn.IsPoint() && isTypeError {
data, _, err := ph.File().Read(ctx)
if err != nil {
return protocol.Range{}, err
}
if s, err := spn.WithOffset(m.Converter); err == nil {
start := s.Start()
offset := start.Offset()

View File

@ -27,7 +27,7 @@ type pkg struct {
mode source.ParseMode
files []source.ParseGoHandle
errors []source.Error
errors []*source.Error
imports map[packagePath]*pkg
types *types.Package
typesInfo *types.Info
@ -79,7 +79,7 @@ func (p *pkg) GetSyntax(ctx context.Context) []*ast.File {
return syntax
}
func (p *pkg) GetErrors() []source.Error {
func (p *pkg) GetErrors() []*source.Error {
return p.errors
}

View File

@ -5,12 +5,10 @@
package source
import (
"bytes"
"context"
"fmt"
"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/telemetry"
"golang.org/x/tools/internal/span"
@ -30,19 +28,17 @@ type Diagnostic struct {
Related []RelatedInformation
}
type SuggestedFix struct {
Title string
Edits map[span.URI][]protocol.TextEdit
}
type RelatedInformation struct {
URI span.URI
Range protocol.Range
Message string
}
type DiagnosticSeverity int
const (
SeverityWarning DiagnosticSeverity = iota
SeverityError
)
func Diagnostics(ctx context.Context, view View, f File, disabledAnalyses map[string]struct{}) (map[span.URI][]Diagnostic, string, error) {
ctx, done := trace.StartSpan(ctx, "source.Diagnostics", telemetry.File.Of(f.URI()))
defer done()
@ -79,7 +75,7 @@ func Diagnostics(ctx context.Context, view View, f File, disabledAnalyses map[st
// Prepare any additional reports for the errors in this package.
for _, err := range pkg.GetErrors() {
if err.Kind != packages.ListError {
if err.Kind != ListError {
continue
}
clearReports(view, reports, err.URI)
@ -119,7 +115,7 @@ func diagnostics(ctx context.Context, view View, pkg Package, reports map[span.U
for _, err := range pkg.GetErrors() {
diag := &Diagnostic{
URI: err.URI,
Message: err.Msg,
Message: err.Message,
Range: err.Range,
Severity: protocol.SeverityError,
}
@ -129,13 +125,13 @@ func diagnostics(ctx context.Context, view View, pkg Package, reports map[span.U
diagSets[diag.URI] = set
}
switch err.Kind {
case packages.ParseError:
case ParseError:
set.parseErrors = append(set.parseErrors, diag)
diag.Source = "syntax"
case packages.TypeError:
case TypeError:
set.typeErrors = append(set.typeErrors, diag)
diag.Source = "compiler"
default:
case ListError:
set.listErrors = append(set.listErrors, diag)
diag.Source = "go list"
}
@ -162,148 +158,39 @@ func diagnostics(ctx context.Context, view View, pkg Package, reports map[span.U
}
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 {
for _, diag := range diags {
diagnostic, err := toDiagnostic(ctx, snapshot.View(), diag, a.Name)
if err != nil {
return err
}
addReport(snapshot.View(), reports, diagnostic.URI, diagnostic)
var analyzers []*analysis.Analyzer
for _, a := range snapshot.View().Options().Analyzers {
if _, ok := disabledAnalyses[a.Name]; ok {
continue
}
return nil
}); err != nil {
analyzers = append(analyzers, a)
}
diagnostics, err := snapshot.Analyze(ctx, cph.ID(), analyzers)
if err != nil {
return err
}
// For caching diagnostics.
// TODO(https://golang.org/issue/32443): Cache diagnostics on the snapshot.
pkg, err := cph.Check(ctx)
if err != nil {
return err
}
// Report diagnostics and errors from root analyzers.
var sdiags []Diagnostic
for a, diags := range diagnostics {
for _, diag := range diags {
sdiag := toDiagnostic(diag, a.Name)
addReport(snapshot.View(), reports, sdiag)
sdiags = append(sdiags, sdiag)
}
pkg.SetDiagnostics(a, sdiags)
}
return nil
}
func packageForSpan(ctx context.Context, view View, spn span.Span) (Package, error) {
f, err := view.GetFile(ctx, spn.URI())
if err != nil {
return nil, err
}
// If the package has changed since these diagnostics were computed,
// this may be incorrect. Should the package be associated with the diagnostic?
_, cphs, err := view.CheckPackageHandles(ctx, f)
if err != nil {
return nil, err
}
cph, err := NarrowestCheckPackageHandle(cphs)
if err != nil {
return nil, err
}
return cph.Cached(ctx)
}
func toDiagnostic(ctx context.Context, view View, diag *analysis.Diagnostic, category string) (Diagnostic, error) {
spn, err := span.NewRange(view.Session().Cache().FileSet(), diag.Pos, diag.End).Span()
if err != nil {
return Diagnostic{}, err
}
pkg, err := packageForSpan(ctx, view, spn)
if err != nil {
return Diagnostic{}, err
}
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
}
fixes, err := suggestedFixes(ctx, view, pkg, diag)
if err != nil {
return Diagnostic{}, err
}
related, err := relatedInformation(ctx, view, diag)
if err != nil {
return Diagnostic{}, err
}
// This is a bit of a hack, but clients > 3.15 will be able to grey out unnecessary code.
// If we are deleting code as part of all of our suggested fixes, assume that this is dead code.
// TODO(golang/go/#34508): Return these codes from the diagnostics themselves.
var tags []protocol.DiagnosticTag
if onlyDeletions(fixes) {
tags = append(tags, protocol.Unnecessary)
}
if diag.Category != "" {
category += "." + diag.Category
}
return Diagnostic{
URI: spn.URI(),
Range: rng,
Source: category,
Message: diag.Message,
Severity: protocol.SeverityWarning,
SuggestedFixes: fixes,
Tags: tags,
Related: related,
}, nil
}
func relatedInformation(ctx context.Context, view View, diag *analysis.Diagnostic) ([]RelatedInformation, error) {
var out []RelatedInformation
for _, related := range diag.Related {
r := span.NewRange(view.Session().Cache().FileSet(), related.Pos, related.End)
spn, err := r.Span()
if err != nil {
return nil, err
}
pkg, err := packageForSpan(ctx, view, spn)
if err != nil {
return nil, err
}
rng, err := spanToRange(ctx, view, pkg, spn, false)
if err != nil {
return nil, err
}
out = append(out, RelatedInformation{
URI: spn.URI(),
Range: rng,
Message: related.Message,
})
}
return out, 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, 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 clearReports(v View, reports map[span.URI][]Diagnostic, uri span.URI) {
if v.Ignore(uri) {
return
@ -311,12 +198,12 @@ func clearReports(v View, reports map[span.URI][]Diagnostic, uri span.URI) {
reports[uri] = []Diagnostic{}
}
func addReport(v View, reports map[span.URI][]Diagnostic, uri span.URI, diagnostic Diagnostic) {
if v.Ignore(uri) {
func addReport(v View, reports map[span.URI][]Diagnostic, diagnostic Diagnostic) {
if v.Ignore(diagnostic.URI) {
return
}
if _, ok := reports[uri]; ok {
reports[uri] = append(reports[uri], diagnostic)
if _, ok := reports[diagnostic.URI]; ok {
reports[diagnostic.URI] = append(reports[diagnostic.URI], diagnostic)
}
}
@ -332,38 +219,42 @@ func singleDiagnostic(uri span.URI, format string, a ...interface{}) map[span.UR
}
}
func runAnalyses(ctx context.Context, snapshot Snapshot, cph CheckPackageHandle, disabledAnalyses map[string]struct{}, report func(diag []*analysis.Diagnostic, a *analysis.Analyzer) error) error {
var analyzers []*analysis.Analyzer
for _, a := range snapshot.View().Options().Analyzers {
if _, ok := disabledAnalyses[a.Name]; ok {
continue
}
analyzers = append(analyzers, a)
func toDiagnostic(e *Error, category string) Diagnostic {
// This is a bit of a hack, but clients > 3.15 will be able to grey out unnecessary code.
// If we are deleting code as part of all of our suggested fixes, assume that this is dead code.
// TODO(golang/go/#34508): Return these codes from the diagnostics themselves.
var tags []protocol.DiagnosticTag
if onlyDeletions(e.SuggestedFixes) {
tags = append(tags, protocol.Unnecessary)
}
diagnostics, err := snapshot.Analyze(ctx, cph.ID(), analyzers)
if err != nil {
return err
if e.Category != "" {
category += "." + e.Category
}
// Report diagnostics and errors from root analyzers.
var sdiags []Diagnostic
for a, diags := range diagnostics {
if err := report(diags, a); err != nil {
return err
}
for _, diag := range diags {
sdiag, err := toDiagnostic(ctx, snapshot.View(), diag, a.Name)
if err != nil {
return err
}
sdiags = append(sdiags, sdiag)
}
pkg, err := cph.Check(ctx)
if err != nil {
return err
}
pkg.SetDiagnostics(a, sdiags)
return Diagnostic{
URI: e.URI,
Range: e.Range,
Message: e.Message,
Source: category,
Severity: protocol.SeverityWarning,
Tags: tags,
SuggestedFixes: e.SuggestedFixes,
Related: e.Related,
}
return nil
}
// onlyDeletions returns true if all of the suggested fixes are deletions.
func onlyDeletions(fixes []SuggestedFix) bool {
for _, fix := range fixes {
for _, edits := range fix.Edits {
for _, edit := range edits {
if edit.NewText != "" {
return false
}
if protocol.ComparePosition(edit.Range.Start, edit.Range.End) == 0 {
return false
}
}
}
}
return true
}

View File

@ -10,7 +10,6 @@ import (
"context"
"go/format"
"golang.org/x/tools/go/packages"
"golang.org/x/tools/internal/imports"
"golang.org/x/tools/internal/lsp/diff"
"golang.org/x/tools/internal/lsp/protocol"
@ -269,7 +268,7 @@ func CandidateImports(ctx context.Context, view View, filename string) (pkgs []i
// hasParseErrors returns true if the given file has parse errors.
func hasParseErrors(pkg Package, uri span.URI) bool {
for _, err := range pkg.GetErrors() {
if err.URI == uri && err.Kind == packages.ParseError {
if err.URI == uri && err.Kind == ParseError {
return true
}
}
@ -278,7 +277,7 @@ func hasParseErrors(pkg Package, uri span.URI) bool {
func hasListErrors(pkg Package) bool {
for _, err := range pkg.GetErrors() {
if err.Kind == packages.ListError {
if err.Kind == ListError {
return true
}
}

View File

@ -1,67 +1 @@
package source
import (
"context"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/internal/lsp/protocol"
"golang.org/x/tools/internal/span"
)
type SuggestedFix struct {
Title string
Edits map[span.URI][]protocol.TextEdit
}
func suggestedFixes(ctx context.Context, view View, pkg Package, diag *analysis.Diagnostic) ([]SuggestedFix, error) {
var fixes []SuggestedFix
for _, fix := range diag.SuggestedFixes {
edits := make(map[span.URI][]protocol.TextEdit)
for _, e := range fix.TextEdits {
posn := view.Session().Cache().FileSet().Position(e.Pos)
uri := span.FileURI(posn.Filename)
ph, _, err := pkg.FindFile(ctx, uri)
if err != nil {
return nil, err
}
_, m, _, err := ph.Cached(ctx)
if err != nil {
return nil, err
}
mrng, err := posToRange(ctx, view, m, e.Pos, e.End)
if err != nil {
return nil, err
}
rng, err := mrng.Range()
if err != nil {
return nil, err
}
edits[uri] = append(edits[uri], protocol.TextEdit{
Range: rng,
NewText: string(e.NewText),
})
}
fixes = append(fixes, SuggestedFix{
Title: fix.Message,
Edits: edits,
})
}
return fixes, nil
}
// onlyDeletions returns true if all of the suggested fixes are deletions.
func onlyDeletions(fixes []SuggestedFix) bool {
for _, fix := range fixes {
for _, edits := range fix.Edits {
for _, edit := range edits {
if edit.NewText != "" {
return false
}
if protocol.ComparePosition(edit.Range.Start, edit.Range.End) == 0 {
return false
}
}
}
}
return true
}

View File

@ -262,7 +262,7 @@ type Snapshot interface {
View() View
// Analyze runs the analyses for the given package at this snapshot.
Analyze(ctx context.Context, id string, analyzers []*analysis.Analyzer) (map[*analysis.Analyzer][]*analysis.Diagnostic, error)
Analyze(ctx context.Context, id string, analyzers []*analysis.Analyzer) (map[*analysis.Analyzer][]*Error, error)
}
// File represents a source file of any type.
@ -280,7 +280,7 @@ type Package interface {
Files() []ParseGoHandle
File(uri span.URI) (ParseGoHandle, error)
GetSyntax(context.Context) []*ast.File
GetErrors() []Error
GetErrors() []*Error
GetTypes() *types.Package
GetTypesInfo() *types.Info
GetTypesSizes() types.Sizes
@ -298,14 +298,27 @@ type Package interface {
}
type Error struct {
Msg string
URI span.URI
Range protocol.Range
Kind packages.ErrorKind
URI span.URI
Range protocol.Range
Kind ErrorKind
Message string
Category string
SuggestedFixes []SuggestedFix
Related []RelatedInformation
}
type ErrorKind int
const (
UnknownError = ErrorKind(iota)
ListError
ParseError
TypeError
Analysis
)
func (e *Error) Error() string {
return fmt.Sprintf("%s:%s: %s", e.URI, e.Range, e.Msg)
return fmt.Sprintf("%s:%s: %s", e.URI, e.Range, e.Message)
}
type BuiltinPackage interface {