loader: better error message on import cycles

Этот коммит содержится в:
Konstantin Yegupov 2019-01-24 17:25:16 +10:00 коммит произвёл Ayke van Laethem
родитель 4f4d7976c6
коммит e6d90d89fa
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E97FF5335DFDFDED
2 изменённых файлов: 24 добавлений и 7 удалений

Просмотреть файл

@ -1,5 +1,10 @@
package loader package loader
import (
"go/token"
"strings"
)
// Errors contains a list of parser errors or a list of typechecker errors for // Errors contains a list of parser errors or a list of typechecker errors for
// the given package. // the given package.
type Errors struct { 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 // packages is a list from the root package to the leaf package that imports one
// of the packages in the list. // of the packages in the list.
type ImportCycleError struct { type ImportCycleError struct {
Packages []string Packages []string
ImportPositions []token.Position
} }
func (e *ImportCycleError) Error() string { func (e *ImportCycleError) Error() string {
msg := "import cycle: " + e.Packages[0] var msg strings.Builder
for _, path := range e.Packages[1:] { msg.WriteString("import cycle:\n\t")
msg += " → " + path 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() err := pkg.importRecursively()
if err != nil { if err != nil {
if err, ok := err.(*ImportCycleError); ok { 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 return err
} }
@ -339,10 +341,13 @@ func (p *Package) importRecursively() error {
return err return err
} }
if importedPkg.Importing { if importedPkg.Importing {
return &ImportCycleError{[]string{p.ImportPath, importedPkg.ImportPath}} return &ImportCycleError{[]string{p.ImportPath, importedPkg.ImportPath}, p.ImportPos[to]}
} }
err = importedPkg.importRecursively() err = importedPkg.importRecursively()
if err != nil { if err != nil {
if err, ok := err.(*ImportCycleError); ok {
err.Packages = append([]string{p.ImportPath}, err.Packages...)
}
return err return err
} }
p.Imports[to] = importedPkg p.Imports[to] = importedPkg