Browse Source
loader: better error message on import cycles
pull/156/head
Konstantin Yegupov
6 years ago
committed by
Ayke van Laethem
No known key found for this signature in database
GPG Key ID: E97FF5335DFDFDED
2 changed files with
24 additions and
7 deletions
-
loader/errors.go
-
loader/loader.go
|
|
@ -1,5 +1,10 @@ |
|
|
|
package loader |
|
|
|
|
|
|
|
import ( |
|
|
|
"go/token" |
|
|
|
"strings" |
|
|
|
) |
|
|
|
|
|
|
|
// Errors contains a list of parser errors or a list of typechecker errors for
|
|
|
|
// the given package.
|
|
|
|
type Errors struct { |
|
|
@ -15,13 +20,20 @@ func (e Errors) Error() string { |
|
|
|
// packages is a list from the root package to the leaf package that imports one
|
|
|
|
// of the packages in the list.
|
|
|
|
type ImportCycleError struct { |
|
|
|
Packages []string |
|
|
|
Packages []string |
|
|
|
ImportPositions []token.Position |
|
|
|
} |
|
|
|
|
|
|
|
func (e *ImportCycleError) Error() string { |
|
|
|
msg := "import cycle: " + e.Packages[0] |
|
|
|
for _, path := range e.Packages[1:] { |
|
|
|
msg += " → " + path |
|
|
|
var msg strings.Builder |
|
|
|
msg.WriteString("import cycle:\n\t") |
|
|
|
msg.WriteString(strings.Join(e.Packages, "\n\t")) |
|
|
|
msg.WriteString("\n at ") |
|
|
|
for i, pos := range e.ImportPositions { |
|
|
|
if i > 0 { |
|
|
|
msg.WriteString(", ") |
|
|
|
} |
|
|
|
msg.WriteString(pos.String()) |
|
|
|
} |
|
|
|
return msg |
|
|
|
return msg.String() |
|
|
|
} |
|
|
|
|
|
@ -166,7 +166,9 @@ func (p *Program) Parse() error { |
|
|
|
err := pkg.importRecursively() |
|
|
|
if err != nil { |
|
|
|
if err, ok := err.(*ImportCycleError); ok { |
|
|
|
err.Packages = append([]string{pkg.ImportPath}, err.Packages...) |
|
|
|
if pkg.ImportPath != err.Packages[0] { |
|
|
|
err.Packages = append([]string{pkg.ImportPath}, err.Packages...) |
|
|
|
} |
|
|
|
} |
|
|
|
return err |
|
|
|
} |
|
|
@ -339,10 +341,13 @@ func (p *Package) importRecursively() error { |
|
|
|
return err |
|
|
|
} |
|
|
|
if importedPkg.Importing { |
|
|
|
return &ImportCycleError{[]string{p.ImportPath, importedPkg.ImportPath}} |
|
|
|
return &ImportCycleError{[]string{p.ImportPath, importedPkg.ImportPath}, p.ImportPos[to]} |
|
|
|
} |
|
|
|
err = importedPkg.importRecursively() |
|
|
|
if err != nil { |
|
|
|
if err, ok := err.(*ImportCycleError); ok { |
|
|
|
err.Packages = append([]string{p.ImportPath}, err.Packages...) |
|
|
|
} |
|
|
|
return err |
|
|
|
} |
|
|
|
p.Imports[to] = importedPkg |
|
|
|