mirror of https://github.com/golang/go.git
internal/lsp: add diagnostic on import causing import cycle
After the addition of golang/go#35964, the import cycle error now has the import stack attached in the message. This CL parses that stack and attached the import cycle diagnostic to the import versus just adding it to the first character of the .go file. Fixes golang/go#33085 Change-Id: I6f5f067c338879b898829951236f816aa63d9dfa Reviewed-on: https://go-review.googlesource.com/c/tools/+/210942 Run-TryBot: Rohan Challa <rohan@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
parent
74e303f875
commit
7ebc6af015
|
|
@ -331,7 +331,6 @@ func typeCheck(ctx context.Context, fset *token.FileSet, m *metadata, mode sourc
|
|||
return nil, ctx.Err()
|
||||
}
|
||||
|
||||
// TODO(golang/go#35964): Propagate `go list` errors here when go/packages supports it.
|
||||
for _, e := range rawErrors {
|
||||
srcErr, err := sourceError(ctx, fset, pkg, e)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import (
|
|||
"go/scanner"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
|
|
@ -30,14 +32,18 @@ func sourceError(ctx context.Context, fset *token.FileSet, pkg *pkg, e interface
|
|||
)
|
||||
switch e := e.(type) {
|
||||
case packages.Error:
|
||||
kind = toSourceErrorKind(e.Kind)
|
||||
var ok bool
|
||||
msg, spn, ok = parseGoListImportCycleError(ctx, fset, e, pkg)
|
||||
if ok {
|
||||
break
|
||||
}
|
||||
|
||||
if e.Pos == "" {
|
||||
spn = parseGoListError(e.Msg)
|
||||
} else {
|
||||
spn = span.Parse(e.Pos)
|
||||
}
|
||||
msg = e.Msg
|
||||
kind = toSourceErrorKind(e.Kind)
|
||||
|
||||
// If the range can't be derived from the parseGoListError function, then we do not have a valid position.
|
||||
if _, err := spanToRange(ctx, pkg, spn); err != nil && e.Pos == "" {
|
||||
return &source.Error{
|
||||
|
|
@ -45,7 +51,6 @@ func sourceError(ctx context.Context, fset *token.FileSet, pkg *pkg, e interface
|
|||
Kind: kind,
|
||||
}, nil
|
||||
}
|
||||
|
||||
case *scanner.Error:
|
||||
msg = e.Msg
|
||||
kind = source.ParseError
|
||||
|
|
@ -249,3 +254,37 @@ func parseGoListError(input string) span.Span {
|
|||
}
|
||||
return span.Parse(input[:msgIndex])
|
||||
}
|
||||
|
||||
func parseGoListImportCycleError(ctx context.Context, fset *token.FileSet, e packages.Error, pkg *pkg) (string, span.Span, bool) {
|
||||
re := regexp.MustCompile(`(.*): import stack: \[(.+)\]`)
|
||||
matches := re.FindStringSubmatch(strings.TrimSpace(e.Msg))
|
||||
if len(matches) < 3 {
|
||||
return e.Msg, span.Span{}, false
|
||||
}
|
||||
msg := matches[1]
|
||||
importList := strings.Split(matches[2], " ")
|
||||
// Since the error is relative to the current package. The import that is causing
|
||||
// the import cycle error is the second one in the list.
|
||||
if len(importList) < 2 {
|
||||
return msg, span.Span{}, false
|
||||
}
|
||||
// Imports have quotation marks around them.
|
||||
circImp := strconv.Quote(importList[1])
|
||||
for _, ph := range pkg.compiledGoFiles {
|
||||
fh, _, _, err := ph.Parse(ctx)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
// Search file imports for the import that is causing the import cycle.
|
||||
for _, imp := range fh.Imports {
|
||||
if imp.Path.Value == circImp {
|
||||
spn, err := span.NewRange(fset, imp.Pos(), imp.End()).Span()
|
||||
if err != nil {
|
||||
return msg, span.Span{}, false
|
||||
}
|
||||
return msg, spn, true
|
||||
}
|
||||
}
|
||||
}
|
||||
return msg, span.Span{}, false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
package b //@diag("", "go list", "import cycle not allowed: import stack: [golang.org/x/tools/internal/lsp/circular/b golang.org/x/tools/internal/lsp/circular/one golang.org/x/tools/internal/lsp/circular/b]")
|
||||
|
||||
import (
|
||||
"golang.org/x/tools/internal/lsp/circular/one"
|
||||
)
|
||||
|
||||
func Test1() {
|
||||
one.Test()
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package b
|
||||
|
||||
import (
|
||||
_ "golang.org/x/tools/internal/lsp/circular/double/one" //@diag("_ \"golang.org/x/tools/internal/lsp/circular/double/one\"", "go list", "import cycle not allowed")
|
||||
)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package one
|
||||
|
||||
import (
|
||||
_ "golang.org/x/tools/internal/lsp/circular/double/b"
|
||||
)
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
package one
|
||||
|
||||
import (
|
||||
"golang.org/x/tools/internal/lsp/circular/b"
|
||||
)
|
||||
|
||||
func Test() {
|
||||
b.Test1()
|
||||
}
|
||||
|
|
@ -1,12 +1,5 @@
|
|||
package circular //@diag("", "go list", "import cycle not allowed: import stack: [golang.org/x/tools/internal/lsp/circular golang.org/x/tools/internal/lsp/circular]")
|
||||
package circular
|
||||
|
||||
import (
|
||||
"golang.org/x/tools/internal/lsp/circular"
|
||||
_ "golang.org/x/tools/internal/lsp/circular" //@diag("_ \"golang.org/x/tools/internal/lsp/circular\"", "go list", "import cycle not allowed")
|
||||
)
|
||||
|
||||
func print() {
|
||||
Test()
|
||||
}
|
||||
|
||||
func Test() {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
package a
|
||||
|
||||
import (
|
||||
_ "golang.org/x/tools/internal/lsp/circular/triple/b" //@diag("_ \"golang.org/x/tools/internal/lsp/circular/triple/b\"", "go list", "import cycle not allowed")
|
||||
)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package b
|
||||
|
||||
import (
|
||||
_ "golang.org/x/tools/internal/lsp/circular/triple/c"
|
||||
)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package c
|
||||
|
||||
import (
|
||||
_ "golang.org/x/tools/internal/lsp/circular/triple/a"
|
||||
)
|
||||
|
|
@ -6,7 +6,7 @@ DeepCompletionsCount = 5
|
|||
FuzzyCompletionsCount = 7
|
||||
RankedCompletionsCount = 26
|
||||
CaseSensitiveCompletionsCount = 4
|
||||
DiagnosticsCount = 34
|
||||
DiagnosticsCount = 35
|
||||
FoldingRangesCount = 2
|
||||
FormatCount = 6
|
||||
ImportCount = 7
|
||||
|
|
|
|||
Loading…
Reference in New Issue