mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-16 10:43:29 +00:00
loader: handle go list errors inside TinyGo
Instead of exiting with an error, handle these errors internally. This will enable a few improvements in the future.
This commit is contained in:
+17
-1
@@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@@ -16,6 +17,10 @@ import (
|
|||||||
func TestErrors(t *testing.T) {
|
func TestErrors(t *testing.T) {
|
||||||
for _, name := range []string{
|
for _, name := range []string{
|
||||||
"cgo",
|
"cgo",
|
||||||
|
"loader-importcycle",
|
||||||
|
"loader-invaliddep",
|
||||||
|
"loader-invalidpackage",
|
||||||
|
"loader-nopackage",
|
||||||
"syntax",
|
"syntax",
|
||||||
"types",
|
"types",
|
||||||
} {
|
} {
|
||||||
@@ -57,11 +62,22 @@ func testErrorMessages(t *testing.T, filename string) {
|
|||||||
actual := strings.TrimRight(buf.String(), "\n")
|
actual := strings.TrimRight(buf.String(), "\n")
|
||||||
|
|
||||||
// Check whether the error is as expected.
|
// Check whether the error is as expected.
|
||||||
if actual != expected {
|
if canonicalizeErrors(actual) != canonicalizeErrors(expected) {
|
||||||
t.Errorf("expected error:\n%s\ngot:\n%s", indentText(expected, "> "), indentText(actual, "> "))
|
t.Errorf("expected error:\n%s\ngot:\n%s", indentText(expected, "> "), indentText(actual, "> "))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func canonicalizeErrors(text string) string {
|
||||||
|
// Fix for Windows: replace all backslashes with forward slashes so that
|
||||||
|
// paths will be the same as on POSIX systems.
|
||||||
|
// (It may also change some other backslashes, but since this is only for
|
||||||
|
// comparing text it should be fine).
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
text = strings.ReplaceAll(text, "\\", "/")
|
||||||
|
}
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
// Indent the given text with a given indentation string.
|
// Indent the given text with a given indentation string.
|
||||||
func indentText(text, indent string) string {
|
func indentText(text, indent string) string {
|
||||||
return indent + strings.ReplaceAll(text, "\n", "\n"+indent)
|
return indent + strings.ReplaceAll(text, "\n", "\n"+indent)
|
||||||
|
|||||||
+18
-3
@@ -128,7 +128,7 @@ func Load(config *compileopts.Config, inputPkg string, typeChecker types.Config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// List the dependencies of this package, in raw JSON format.
|
// List the dependencies of this package, in raw JSON format.
|
||||||
extraArgs := []string{"-json", "-deps"}
|
extraArgs := []string{"-json", "-deps", "-e"}
|
||||||
if config.TestConfig.CompileTestBinary {
|
if config.TestConfig.CompileTestBinary {
|
||||||
extraArgs = append(extraArgs, "-test")
|
extraArgs = append(extraArgs, "-test")
|
||||||
}
|
}
|
||||||
@@ -149,6 +149,7 @@ func Load(config *compileopts.Config, inputPkg string, typeChecker types.Config)
|
|||||||
|
|
||||||
// Parse the returned json from `go list`.
|
// Parse the returned json from `go list`.
|
||||||
decoder := json.NewDecoder(buf)
|
decoder := json.NewDecoder(buf)
|
||||||
|
var pkgErrors []error
|
||||||
for {
|
for {
|
||||||
pkg := &Package{
|
pkg := &Package{
|
||||||
program: p,
|
program: p,
|
||||||
@@ -188,6 +189,12 @@ func Load(config *compileopts.Config, inputPkg string, typeChecker types.Config)
|
|||||||
pos.Filename = strings.Join(fields[:len(fields)-1], ":")
|
pos.Filename = strings.Join(fields[:len(fields)-1], ":")
|
||||||
pos.Line, _ = strconv.Atoi(fields[len(fields)-1])
|
pos.Line, _ = strconv.Atoi(fields[len(fields)-1])
|
||||||
}
|
}
|
||||||
|
if abs, err := filepath.Abs(pos.Filename); err == nil {
|
||||||
|
// Make the path absolute, so that error messages will be
|
||||||
|
// prettier (it will be turned back into a relative path
|
||||||
|
// when printing the error).
|
||||||
|
pos.Filename = abs
|
||||||
|
}
|
||||||
pos.Filename = p.getOriginalPath(pos.Filename)
|
pos.Filename = p.getOriginalPath(pos.Filename)
|
||||||
}
|
}
|
||||||
err := scanner.Error{
|
err := scanner.Error{
|
||||||
@@ -195,10 +202,11 @@ func Load(config *compileopts.Config, inputPkg string, typeChecker types.Config)
|
|||||||
Msg: pkg.Error.Err,
|
Msg: pkg.Error.Err,
|
||||||
}
|
}
|
||||||
if len(pkg.Error.ImportStack) != 0 {
|
if len(pkg.Error.ImportStack) != 0 {
|
||||||
return nil, Error{
|
pkgErrors = append(pkgErrors, Error{
|
||||||
ImportStack: pkg.Error.ImportStack,
|
ImportStack: pkg.Error.ImportStack,
|
||||||
Err: err,
|
Err: err,
|
||||||
}
|
})
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -241,6 +249,13 @@ func Load(config *compileopts.Config, inputPkg string, typeChecker types.Config)
|
|||||||
p.Packages[pkg.ImportPath] = pkg
|
p.Packages[pkg.ImportPath] = pkg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(pkgErrors) != 0 {
|
||||||
|
// TODO: use errors.Join in Go 1.20.
|
||||||
|
return nil, Errors{
|
||||||
|
Errs: pkgErrors,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if config.TestConfig.CompileTestBinary && !strings.HasSuffix(p.sorted[len(p.sorted)-1].ImportPath, ".test") {
|
if config.TestConfig.CompileTestBinary && !strings.HasSuffix(p.sorted[len(p.sorted)-1].ImportPath, ".test") {
|
||||||
// Trying to compile a test binary but there are no test files in this
|
// Trying to compile a test binary but there are no test files in this
|
||||||
// package.
|
// package.
|
||||||
|
|||||||
@@ -1340,15 +1340,31 @@ func printCompilerError(err error, logln func(...interface{}), wd string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case loader.Errors:
|
case loader.Errors:
|
||||||
logln("#", err.Pkg.ImportPath)
|
// Parser errors, typechecking errors, or `go list` errors.
|
||||||
|
// err.Pkg is nil for `go list` errors.
|
||||||
|
if err.Pkg != nil {
|
||||||
|
logln("#", err.Pkg.ImportPath)
|
||||||
|
}
|
||||||
for _, err := range err.Errs {
|
for _, err := range err.Errs {
|
||||||
printCompilerError(err, logln, wd)
|
printCompilerError(err, logln, wd)
|
||||||
}
|
}
|
||||||
case loader.Error:
|
case loader.Error:
|
||||||
logln(err.Err.Error())
|
if err.Err.Pos.Filename != "" {
|
||||||
logln("package", err.ImportStack[0])
|
// Probably a syntax error in a dependency.
|
||||||
for _, pkgPath := range err.ImportStack[1:] {
|
printCompilerError(err.Err, logln, wd)
|
||||||
logln("\timports", pkgPath)
|
} else {
|
||||||
|
// Probably an "import cycle not allowed" error.
|
||||||
|
logln("package", err.ImportStack[0])
|
||||||
|
for i := 1; i < len(err.ImportStack); i++ {
|
||||||
|
pkgPath := err.ImportStack[i]
|
||||||
|
if i == len(err.ImportStack)-1 {
|
||||||
|
// last package
|
||||||
|
logln("\timports", pkgPath+": "+err.Err.Error())
|
||||||
|
} else {
|
||||||
|
// not the last pacakge
|
||||||
|
logln("\timports", pkgPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case *builder.MultiError:
|
case *builder.MultiError:
|
||||||
for _, err := range err.Errs {
|
for _, err := range err.Errs {
|
||||||
|
|||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package importcycle
|
||||||
|
|
||||||
|
import _ "github.com/tinygo-org/tinygo/testdata/errors/importcycle"
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
ppackage // syntax error
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import _ "github.com/tinygo-org/tinygo/testdata/errors/importcycle"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERROR: package command-line-arguments
|
||||||
|
// ERROR: imports github.com/tinygo-org/tinygo/testdata/errors/importcycle
|
||||||
|
// ERROR: imports github.com/tinygo-org/tinygo/testdata/errors/importcycle: import cycle not allowed
|
||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import _ "github.com/tinygo-org/tinygo/testdata/errors/invaliddep"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERROR: invaliddep/invaliddep.go:1:1: expected 'package', found ppackage
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
ppackage // syntax error
|
||||||
|
|
||||||
|
// ERROR: loader-invalidpackage.go:1:1: expected 'package', found ppackage
|
||||||
Vendored
+14
@@ -0,0 +1,14 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/tinygo-org/tinygo/testdata/errors/non-existing-package"
|
||||||
|
_ "github.com/tinygo-org/tinygo/testdata/errors/non-existing-package-2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERROR: loader-nopackage.go:4:2: no required module provides package github.com/tinygo-org/tinygo/testdata/errors/non-existing-package; to add it:
|
||||||
|
// ERROR: go get github.com/tinygo-org/tinygo/testdata/errors/non-existing-package
|
||||||
|
// ERROR: loader-nopackage.go:5:2: no required module provides package github.com/tinygo-org/tinygo/testdata/errors/non-existing-package-2; to add it:
|
||||||
|
// ERROR: go get github.com/tinygo-org/tinygo/testdata/errors/non-existing-package-2
|
||||||
Reference in New Issue
Block a user