diff --git a/gnovm/cmd/gno/lint.go b/gnovm/cmd/gno/lint.go index c1974094da0..5e43bc3393e 100644 --- a/gnovm/cmd/gno/lint.go +++ b/gnovm/cmd/gno/lint.go @@ -172,27 +172,36 @@ func catchRuntimeError(pkgPath string, stderr io.WriteCloser, action func()) (ha return } hasError = true - switch verr := r.(type) { - case *gno.PreprocessError: - err := verr.Unwrap() - fmt.Fprint(stderr, issueFromError(pkgPath, err).String()+"\n") - case scanner.ErrorList: - for _, err := range verr { - fmt.Fprint(stderr, issueFromError(pkgPath, err).String()+"\n") - } - case error: - fmt.Fprint(stderr, issueFromError(pkgPath, verr).String()+"\n") - case string: - fmt.Fprint(stderr, issueFromError(pkgPath, errors.New(verr)).String()+"\n") - default: - panic(r) - } + printRuntimeError(r, pkgPath, stderr) }() action() return } +func printRuntimeError(r interface{}, pkgPath string, stderr io.WriteCloser) { + switch verr := r.(type) { + case *gno.PreprocessError: + err := verr.Unwrap() + fmt.Fprint(stderr, issueFromError(pkgPath, err).String()+"\n") + case scanner.ErrorList: + for _, err := range verr { + fmt.Fprint(stderr, issueFromError(pkgPath, err).String()+"\n") + } + case error: + fmt.Fprint(stderr, issueFromError(pkgPath, verr).String()+"\n") + case []error: + for _, err := range verr { + // recursive call to handle specifically each error type ex: scanner.ErrorList + printRuntimeError(err, pkgPath, stderr) + } + case string: + fmt.Fprint(stderr, issueFromError(pkgPath, errors.New(verr)).String()+"\n") + default: + panic(r) + } +} + type lintCode int const ( diff --git a/gnovm/cmd/gno/lint_test.go b/gnovm/cmd/gno/lint_test.go index fff05726e53..f499dd03c6c 100644 --- a/gnovm/cmd/gno/lint_test.go +++ b/gnovm/cmd/gno/lint_test.go @@ -19,6 +19,9 @@ func TestLintApp(t *testing.T) { }, { args: []string{"lint", "--set-exit-status=0", "../../tests/integ/several-lint-errors/main.gno"}, stderrShouldContain: "../../tests/integ/several-lint-errors/main.gno:5: expected ';', found example (code=2).\n../../tests/integ/several-lint-errors/main.gno:6", + }, { + args: []string{"lint", "--set-exit-status=0", "../../tests/integ/several-files-multiple-errors/main.gno"}, + stderrShouldContain: "../../tests/integ/several-files-multiple-errors/file2.gno:3: expected 'IDENT', found '{' (code=2).\n../../tests/integ/several-files-multiple-errors/file2.gno:5: expected type, found '}' (code=2).\n../../tests/integ/several-files-multiple-errors/main.gno:5: expected ';', found example (code=2).\n../../tests/integ/several-files-multiple-errors/main.gno:6: expected '}', found 'EOF' (code=2).\n", }, { args: []string{"lint", "--set-exit-status=0", "../../tests/integ/run_main/"}, stderrShouldContain: "./../../tests/integ/run_main: missing 'gno.mod' file (code=1).", diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index e09e06c0418..8c90000379d 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -638,6 +638,7 @@ func loadTestFuncs(pkgName string, t *testFuncs, tfiles *gno.FileSet) *testFuncs func parseMemPackageTests(memPkg *std.MemPackage) (tset, itset *gno.FileSet) { tset = &gno.FileSet{} itset = &gno.FileSet{} + errors := []error{} for _, mfile := range memPkg.Files { if !strings.HasSuffix(mfile.Name, ".gno") { continue // skip this file. @@ -647,7 +648,8 @@ func parseMemPackageTests(memPkg *std.MemPackage) (tset, itset *gno.FileSet) { } n, err := gno.ParseFile(mfile.Name, mfile.Body) if err != nil { - panic(err) + errors = append(errors, err) + continue } if n == nil { panic("should not happen") @@ -667,6 +669,9 @@ func parseMemPackageTests(memPkg *std.MemPackage) (tset, itset *gno.FileSet) { memPkg.Name, memPkg.Name, n.PkgName, mfile)) } } + if len(errors) > 0 { + panic(errors) + } return tset, itset } diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 6f1584dcc28..b5aa57b60ba 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -1172,6 +1172,7 @@ func ReadMemPackageFromList(list []string, pkgPath string) *std.MemPackage { // or [ParseFile] returns an error, ParseMemPackage panics. func ParseMemPackage(memPkg *std.MemPackage) (fset *FileSet) { fset = &FileSet{} + errors := []error{} for _, mfile := range memPkg.Files { if !strings.HasSuffix(mfile.Name, ".gno") || endsWith(mfile.Name, []string{"_test.gno", "_filetest.gno"}) { @@ -1179,7 +1180,8 @@ func ParseMemPackage(memPkg *std.MemPackage) (fset *FileSet) { } n, err := ParseFile(mfile.Name, mfile.Body) if err != nil { - panic(err) + errors = append(errors, err) + continue } if memPkg.Name != string(n.PkgName) { panic(fmt.Sprintf( @@ -1189,6 +1191,9 @@ func ParseMemPackage(memPkg *std.MemPackage) (fset *FileSet) { // add package file. fset.AddFiles(n) } + if len(errors) > 0 { + panic(errors) + } return fset } diff --git a/gnovm/tests/integ/several-files-multiple-errors/file2.gno b/gnovm/tests/integ/several-files-multiple-errors/file2.gno new file mode 100644 index 00000000000..39ec59973ef --- /dev/null +++ b/gnovm/tests/integ/several-files-multiple-errors/file2.gno @@ -0,0 +1,5 @@ +package main + +type{ + +} \ No newline at end of file diff --git a/gnovm/tests/integ/several-files-multiple-errors/gno.mod b/gnovm/tests/integ/several-files-multiple-errors/gno.mod new file mode 100644 index 00000000000..88485411822 --- /dev/null +++ b/gnovm/tests/integ/several-files-multiple-errors/gno.mod @@ -0,0 +1 @@ +module gno.land/tests/severalerrors \ No newline at end of file diff --git a/gnovm/tests/integ/several-files-multiple-errors/main.gno b/gnovm/tests/integ/several-files-multiple-errors/main.gno new file mode 100644 index 00000000000..f29aa7ecd33 --- /dev/null +++ b/gnovm/tests/integ/several-files-multiple-errors/main.gno @@ -0,0 +1,6 @@ +package main + +func main() { + for { + _ example +} \ No newline at end of file