Repository: cloudspannerecosystem/memefish
Pull request #241 (2024-12-23 07:21:21)

Make the default error message one line
Previously, the error `Error()` returned by the parser was a multi-line string. However, Go often returns a new error that wraps the error, so a one-line error message is more convenient. Therefore, the default error message is one-line.

You can get the previous multi-line error message with `FullError()`.



Patch:
diff --git a/error.go b/error.go
index 66cd5d4..5be030f 100644
--- a/error.go
+++ b/error.go
@@ -9,7 +9,7 @@ import (
 
 // MultiError is a list of errors occured on parsing.
 //
-// Note that `ParseXXX` methods returns this wrapped error even if the error is just one.
+// Note that Parse* methods returns this wrapped error even if the error is just one.
 type MultiError []*Error
 
 func (list MultiError) String() string {
@@ -27,9 +27,9 @@ func (list MultiError) Error() string {
 	case 1:
 		return list[0].Error()
 	case 2:
-		return list[0].Error() + "\n(and 1 other error)"
+		return list[0].Error() + " (and 1 other error)"
 	default:
-		return fmt.Sprintf("%s\n(and %d other errors)", list[0].Error(), len(list))
+		return fmt.Sprintf("%s (and %d other errors)", list[0].Error(), len(list)-1)
 	}
 }
 
@@ -37,11 +37,12 @@ func (list MultiError) Error() string {
 func (list MultiError) FullError() string {
 	var message bytes.Buffer
 	for _, err := range list {
-		fmt.Fprintln(&message, err.Error())
+		fmt.Fprintln(&message, err.FullError())
 	}
 	return message.String()
 }
 
+// Error is an error occured on parsing.
 type Error struct {
 	Message  string
 	Position *token.Position
@@ -51,9 +52,14 @@ func (e *Error) String() string {
 	return e.Error()
 }
 
+// Error returns an error message.
 func (e *Error) Error() string {
+	return fmt.Sprintf("syntax error: %s: %s", e.Position, e.Message)
+}
+
+func (e *Error) FullError() string {
 	var message bytes.Buffer
-	fmt.Fprintf(&message, "syntax error: %s: %s", e.Position, e.Message)
+	fmt.Fprint(&message, e.Error())
 	if e.Position.Source != "" {
 		fmt.Fprintf(&message, "\n%s", e.Position.Source)
 	}
diff --git a/tools/util/poslang/expr.go b/tools/util/poslang/expr.go
index 67eeed4..838b2fd 100644
--- a/tools/util/poslang/expr.go
+++ b/tools/util/poslang/expr.go
@@ -43,7 +43,7 @@ type Expr interface {
 	Unparse() string
 }
 
-// Typed expression types has a method EvalXXX.
+// Typed expression types has a method Eval*.
 // This method evaluates the expression on the given any value.
 
 // PosExpr is a POS expression typed with token.Pos.


Test patch:
diff --git a/error_test.go b/error_test.go
index 1da85dd..9dd2bb5 100644
--- a/error_test.go
+++ b/error_test.go
@@ -48,11 +48,7 @@ func TestMultiError(t *testing.T) {
 		},
 		{
 			MultiError{err1},
-			heredoc.Doc(`
-				syntax error: foo:1:1: error 1
-				  1| a b
-				   | ^
-			`),
+			"syntax error: foo:1:1: error 1",
 			heredoc.Doc(`
 				syntax error: foo:1:1: error 1
 				  1| a b
@@ -61,12 +57,19 @@ func TestMultiError(t *testing.T) {
 		},
 		{
 			MultiError{err1, err2},
+			"syntax error: foo:1:1: error 1 (and 1 other error)",
 			heredoc.Doc(`
 				syntax error: foo:1:1: error 1
 				  1| a b
 				   | ^
-				(and 1 other error)
+				syntax error: foo:1:3: error 2
+				  1| a b
+				   |   ^
 			`),
+		},
+		{
+			MultiError{err1, err2, err2},
+			"syntax error: foo:1:1: error 1 (and 2 other errors)",
 			heredoc.Doc(`
 				syntax error: foo:1:1: error 1
 				  1| a b
@@ -74,6 +77,9 @@ func TestMultiError(t *testing.T) {
 				syntax error: foo:1:3: error 2
 				  1| a b
 				   |   ^
+				syntax error: foo:1:3: error 2
+				  1| a b
+				   |   ^
 			`),
 		},
 	} {