@@ -17,6 +17,7 @@ const setProtoOf = Object.setPrototypeOf
17
17
} ;
18
18
19
19
// Thrown when the grammar contains an error.
20
+ /** @type {import("./peg").GrammarError } */
20
21
class GrammarError extends Error {
21
22
constructor ( message , location , diagnostics ) {
22
23
super ( message ) ;
@@ -27,6 +28,10 @@ class GrammarError extends Error {
27
28
diagnostics = [ ] ;
28
29
}
29
30
this . diagnostics = diagnostics ;
31
+ // All problems if this error is thrown by the plugin and not at stage
32
+ // checking phase
33
+ this . stage = null ;
34
+ this . problems = [ [ "error" , message , location , diagnostics ] ] ;
30
35
}
31
36
32
37
toString ( ) {
@@ -51,9 +56,6 @@ class GrammarError extends Error {
51
56
return str ;
52
57
}
53
58
54
- /**
55
- * @typedef SourceText {source: any, text: string}
56
- */
57
59
/**
58
60
* Format the error with associated sources. The `location.source` should have
59
61
* a `toString()` representation in order the result to look nice. If source
@@ -73,7 +75,7 @@ class GrammarError extends Error {
73
75
* | ^^^^
74
76
* ```
75
77
*
76
- * @param {SourceText[] } sources mapping from location source to source text
78
+ * @param {import("./peg"). SourceText[] } sources mapping from location source to source text
77
79
*
78
80
* @returns {string } the formatted error
79
81
*/
@@ -83,6 +85,14 @@ class GrammarError extends Error {
83
85
text : text . split ( / \r \n | \n | \r / g) ,
84
86
} ) ) ;
85
87
88
+ /**
89
+ * Returns a highlighted piece of source to which the `location` points
90
+ *
91
+ * @param {import("./peg").LocationRange } location
92
+ * @param {number } indent How much width in symbols line number strip should have
93
+ * @param {string } message Additional message that will be shown after location
94
+ * @returns {string }
95
+ */
86
96
function entry ( location , indent , message = "" ) {
87
97
let str = "" ;
88
98
const src = srcLines . find ( ( { source } ) => source === location . source ) ;
@@ -109,30 +119,43 @@ ${"".padEnd(indent)} | ${"".padEnd(s.column - 1)}${"".padEnd(last - s.column, "^
109
119
return str ;
110
120
}
111
121
112
- // Calculate maximum width of all lines
113
- let maxLine ;
114
- if ( this . location ) {
115
- maxLine = this . diagnostics . reduce (
116
- ( t , { location } ) => Math . max ( t , location . start . line ) ,
117
- this . location . start . line
118
- ) ;
119
- } else {
120
- maxLine = Math . max . apply (
121
- null ,
122
- this . diagnostics . map ( d => d . location . start . line )
123
- ) ;
124
- }
125
- maxLine = maxLine . toString ( ) . length ;
122
+ /**
123
+ * Returns a formatted representation of the one problem in the error.
124
+ *
125
+ * @param {import("./peg").Severity } severity Importance of the message
126
+ * @param {string } message Test message of the problem
127
+ * @param {import("./peg").LocationRange? } location Location of the problem in the source
128
+ * @param {import("./peg").DiagnosticNote[] } diagnostics Additional notes about the problem
129
+ * @returns {string }
130
+ */
131
+ function formatProblem ( severity , message , location , diagnostics ) {
132
+ // Calculate maximum width of all lines
133
+ let maxLine ;
134
+ if ( location ) {
135
+ maxLine = diagnostics . reduce (
136
+ ( t , { location } ) => Math . max ( t , location . start . line ) ,
137
+ location . start . line
138
+ ) ;
139
+ } else {
140
+ maxLine = Math . max . apply (
141
+ null ,
142
+ diagnostics . map ( d => d . location . start . line )
143
+ ) ;
144
+ }
145
+ maxLine = maxLine . toString ( ) . length ;
126
146
127
- let str = `Error: ${ this . message } ` ;
128
- if ( this . location ) {
129
- str += entry ( this . location , maxLine ) ;
130
- }
131
- for ( const diag of this . diagnostics ) {
132
- str += entry ( diag . location , maxLine , diag . message ) ;
147
+ let str = `${ severity } : ${ message } ` ;
148
+ if ( location ) {
149
+ str += entry ( location , maxLine ) ;
150
+ }
151
+ for ( const diag of diagnostics ) {
152
+ str += entry ( diag . location , maxLine , diag . message ) ;
153
+ }
154
+
155
+ return str ;
133
156
}
134
157
135
- return str ;
158
+ return this . problems . map ( p => formatProblem ( p [ 0 ] , p [ 1 ] , p [ 2 ] , p [ 3 ] ) ) . join ( "\n\n" ) ;
136
159
}
137
160
}
138
161
0 commit comments