Skip to content

Commit e1e10cd

Browse files
committed
better formatting of generic error messages
1 parent 0425da8 commit e1e10cd

File tree

5 files changed

+66
-39
lines changed

5 files changed

+66
-39
lines changed

src/ddperror/error.go

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package ddperror
22

33
import (
44
"fmt"
5+
"path/filepath"
6+
"strings"
57

68
"github.com/DDP-Projekt/Kompilierer/src/token"
79
)
@@ -16,22 +18,52 @@ const (
1618

1719
// Error type for ddp-errors
1820
type Error struct {
19-
Code Code // the error code
20-
Range token.Range // the range the error spans in its source
21-
Msg string // the error message
22-
File string // the filepath (or uri, url or whatever) in which the error occured
23-
Level Level // the level of the error
21+
Code Code // the error code
22+
Range token.Range // the range the error spans in its source
23+
Msg string // the error message
24+
File string // the filepath (or uri, url or whatever) in which the error occured
25+
Level Level // the level of the error
26+
WrappedGenericErrors []Error // optional slice of generic errors wrapped by this error
2427
}
2528

2629
// simple string representation of the error
2730
// should only be used for debugging
2831
// the error-handlers handle the real formatting
2932
func (err Error) String() string {
30-
return fmt.Sprintf("(%04d) %s (Z: %d, S: %d): %s", err.Code, err.File, err.Range.Start.Line, err.Range.Start.Column, err.Msg)
33+
msg := strings.Builder{}
34+
printIndentedError(&msg, err, 0)
35+
return msg.String()
36+
}
37+
38+
const ERROR_INDENT = " "
39+
40+
func printIndentedError(builder *strings.Builder, err Error, indent int) {
41+
printN(builder, indent, ERROR_INDENT)
42+
43+
if indent == 0 {
44+
builder.WriteString(err.Msg)
45+
} else {
46+
fmt.Fprintf(builder, "(%04d) %s (Z: %d, S: %d): %s", err.Code, shortFileName(err.File), err.Range.Start.Line, err.Range.Start.Column, err.Msg)
47+
}
48+
49+
if len(err.WrappedGenericErrors) != 0 {
50+
builder.WriteString(":")
51+
for _, err := range err.WrappedGenericErrors {
52+
builder.WriteString("\n")
53+
printIndentedError(builder, err, indent+1)
54+
if len(err.WrappedGenericErrors) != 0 {
55+
builder.WriteString("\n")
56+
}
57+
}
58+
}
59+
}
60+
61+
func shortFileName(s string) string {
62+
return filepath.Base(s)
3163
}
3264

3365
func (err Error) Error() string {
34-
return err.Msg
66+
return err.String()
3567
}
3668

3769
// create a new Error from the given parameters

src/ddperror/handler.go

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func EmptyHandler(Error) {}
1616
// creates a basic handler that prints the formatted error on a line
1717
func MakeBasicHandler(w io.Writer) Handler {
1818
return func(err Error) {
19-
fmt.Fprintf(w, "%s: %s\n", makeErrorHeader(err, ""), err.Msg)
19+
fmt.Fprintf(w, "%s: %s\n", makeErrorHeader(err, ""), err)
2020
}
2121
}
2222

@@ -36,13 +36,6 @@ func MakeAdvancedHandler(file string, src []byte, w io.Writer) Handler {
3636
return
3737
}
3838

39-
// helper function to print s n-times
40-
printN := func(n int, s string) {
41-
for i := 0; i < n; i++ {
42-
fmt.Fprint(w, s)
43-
}
44-
}
45-
4639
// helper to find the maximum of two uints
4740
uMax := func(a, b uint) uint {
4841
if a > b {
@@ -75,29 +68,29 @@ func MakeAdvancedHandler(file string, src []byte, w io.Writer) Handler {
7568

7669
if lineIndex == rnge.Start.Line-1 {
7770
startLen := replaceAndCount(line[:rnge.Start.Column-1])
78-
printN(startLen, " ")
71+
printN(w, startLen, " ")
7972
restLen := replaceAndCount(line[rnge.Start.Column-1:])
8073
if rnge.Start.Line == rnge.End.Line {
8174
restLen = replaceAndCount(line[rnge.Start.Column-1 : rnge.End.Column-1])
8275
}
83-
printN(restLen, "^")
76+
printN(w, restLen, "^")
8477
} else if lineIndex < rnge.End.Line-1 {
85-
printN(lineStart, " ")
86-
printN(lineLen-lineStart, "^")
78+
printN(w, lineStart, " ")
79+
printN(w, lineLen-lineStart, "^")
8780
} else {
8881
restLen := replaceAndCount(line[:rnge.End.Column-1])
8982
if lineStart < restLen {
90-
printN(lineStart, " ")
91-
printN(lineLen-lineStart, "^")
83+
printN(w, lineStart, " ")
84+
printN(w, lineLen-lineStart, "^")
9285
} else {
93-
printN(restLen, "^")
86+
printN(w, restLen, "^")
9487
}
9588
}
9689
fmt.Fprint(w, "\n")
9790
}
9891

99-
fmt.Fprintf(w, "\n%s.\n\n", err.Msg)
100-
printN(maxLineCount, "-")
92+
fmt.Fprintf(w, "\n%s.\n\n", err)
93+
printN(w, maxLineCount, "-")
10194
fmt.Fprint(w, "\n\n")
10295
}
10396
}
@@ -150,3 +143,10 @@ func (m *Collector) GetHandler() Handler {
150143
m.Errors = append(m.Errors, err)
151144
}
152145
}
146+
147+
// helper function to print s n-times
148+
func printN(w io.Writer, n int, s string) {
149+
for i := 0; i < n; i++ {
150+
fmt.Fprint(w, s)
151+
}
152+
}

src/parser/alias.go

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -130,18 +130,6 @@ func (p *parser) alias() ast.Expression {
130130
}
131131
}
132132

133-
createInstantiationError := func(decl *ast.FuncDecl, errs []ddperror.Error) ddperror.Error {
134-
msg := strings.Builder{}
135-
msg.WriteString(fmt.Sprintf("Es gab Fehler beim Instanziieren der generischen Funktion '%s':", decl.Name()))
136-
137-
for _, err := range errs {
138-
msg.WriteString("\n\t")
139-
msg.WriteString(err.String())
140-
}
141-
142-
return ddperror.New(ddperror.SEM_ERROR_INSTANTIATING_GENERIC_FUNCTION, ddperror.LEVEL_ERROR, p.previous().Range, msg.String(), p.module.FileName)
143-
}
144-
145133
type checkAliasResult struct {
146134
alias ast.Alias
147135
errs []ddperror.Error
@@ -174,7 +162,14 @@ func (p *parser) alias() ast.Expression {
174162

175163
// generic aliases may not be called with typeSensitive = false
176164
if funcAlias, ok := mostFitting.alias.(*ast.FuncAlias); ok && ast.IsGeneric(funcAlias.Func) {
177-
p.errVal(createInstantiationError(funcAlias.Func, mostFitting.errs))
165+
p.errVal(ddperror.Error{
166+
Code: ddperror.SEM_ERROR_INSTANTIATING_GENERIC_FUNCTION,
167+
Level: ddperror.LEVEL_ERROR,
168+
Range: p.previous().Range,
169+
Msg: fmt.Sprintf("Es gab Fehler beim Instanziieren der generischen Funktion '%s'", funcAlias.Func.Name()),
170+
File: p.module.FileName,
171+
WrappedGenericErrors: mostFitting.errs,
172+
})
178173
p.cur = start
179174
return nil
180175
}

src/parser/declarations.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1233,7 +1233,7 @@ func (p *parser) aliasDecl() ast.Statement {
12331233
// scan the raw alias withouth the ""
12341234
var alias *ast.FuncAlias
12351235
var pTokens []*token.Token
1236-
if aliasTokens, err := scanner.ScanAlias(*aliasTok, func(err ddperror.Error) { p.err(err.Code, err.Range, err.Msg) }); err == nil && len(aliasTokens) < 2 { // empty strings are not allowed (we need at leas 1 token + EOF)
1236+
if aliasTokens, err := scanner.ScanAlias(*aliasTok, func(err ddperror.Error) { p.errVal(err) }); err == nil && len(aliasTokens) < 2 { // empty strings are not allowed (we need at leas 1 token + EOF)
12371237
p.err(ddperror.SEM_MALFORMED_ALIAS, aliasTok.Range, "Ein Alias muss mindestens 1 Symbol enthalten")
12381238
} else if err := p.validateFunctionAlias(aliasTokens, funDecl.Parameters); err == nil { // check that the alias fits the function
12391239
if ok, isFun, existingAlias, toks := p.aliasExists(aliasTokens); ok {

src/parser/statements.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ func (p *parser) finishStatement(stmt ast.Statement) ast.Statement {
154154
if p.peek().Type == token.COUNT_MAL {
155155
p.checkStatement(stmt)
156156
if err != nil {
157-
p.err(err.Code, err.Range, err.Msg)
157+
p.errVal(*err)
158158
}
159159
} else {
160160
p.cur = cur

0 commit comments

Comments
 (0)