@herb-tools/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -0
- package/README.md +9 -0
- package/dist/herb-core.browser.js +2704 -0
- package/dist/herb-core.browser.js.map +1 -0
- package/dist/herb-core.cjs +2759 -0
- package/dist/herb-core.cjs.map +1 -0
- package/dist/herb-core.esm.js +2704 -0
- package/dist/herb-core.esm.js.map +1 -0
- package/dist/herb-core.umd.js +2765 -0
- package/dist/herb-core.umd.js.map +1 -0
- package/dist/types/ast.d.ts +4 -0
- package/dist/types/backend.d.ts +24 -0
- package/dist/types/error.d.ts +16 -0
- package/dist/types/errors.d.ts +222 -0
- package/dist/types/herb-backend.d.ts +87 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/lex-result.d.ts +50 -0
- package/dist/types/location.d.ts +18 -0
- package/dist/types/node.d.ts +27 -0
- package/dist/types/nodes.d.ts +682 -0
- package/dist/types/parse-result.d.ts +62 -0
- package/dist/types/position.d.ts +15 -0
- package/dist/types/range.d.ts +12 -0
- package/dist/types/result.d.ts +10 -0
- package/dist/types/token-list.d.ts +16 -0
- package/dist/types/token.d.ts +22 -0
- package/dist/types/util.d.ts +2 -0
- package/dist/types/visitor.d.ts +11 -0
- package/dist/types/warning.d.ts +11 -0
- package/package.json +49 -0
- package/src/ast.ts +7 -0
- package/src/backend.ts +85 -0
- package/src/error.ts +38 -0
- package/src/errors.ts +820 -0
- package/src/herb-backend.ts +152 -0
- package/src/index.ts +15 -0
- package/src/lex-result.ts +78 -0
- package/src/location.ts +51 -0
- package/src/node.ts +106 -0
- package/src/nodes.ts +2294 -0
- package/src/parse-result.ts +101 -0
- package/src/position.ts +38 -0
- package/src/range.ts +35 -0
- package/src/result.ts +26 -0
- package/src/token-list.ts +57 -0
- package/src/token.ts +63 -0
- package/src/util.ts +19 -0
- package/src/visitor.ts +14 -0
- package/src/warning.ts +20 -0
package/src/errors.ts
ADDED
|
@@ -0,0 +1,820 @@
|
|
|
1
|
+
// NOTE: This file is generated by the templates/template.rb script and should not
|
|
2
|
+
// be modified manually. See /Users/marcoroth/Development/herb-release/templates/javascript/packages/core/src/errors.ts.erb
|
|
3
|
+
|
|
4
|
+
import { Location, SerializedLocation } from "./location.js"
|
|
5
|
+
import { Token, SerializedToken } from "./token.js"
|
|
6
|
+
import { HerbError, SerializedHerbError } from "./error.js"
|
|
7
|
+
|
|
8
|
+
type HerbDiagnostic = {
|
|
9
|
+
line: number
|
|
10
|
+
column: number
|
|
11
|
+
endLine: number
|
|
12
|
+
endColumn: number
|
|
13
|
+
message: string
|
|
14
|
+
severity: "error" | "warning" | "info"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type HerbErrorType =
|
|
18
|
+
| "UNEXPECTED_ERROR"
|
|
19
|
+
| "UNEXPECTED_TOKEN_ERROR"
|
|
20
|
+
| "MISSING_OPENING_TAG_ERROR"
|
|
21
|
+
| "MISSING_CLOSING_TAG_ERROR"
|
|
22
|
+
| "TAG_NAMES_MISMATCH_ERROR"
|
|
23
|
+
| "QUOTES_MISMATCH_ERROR"
|
|
24
|
+
| "VOID_ELEMENT_CLOSING_TAG_ERROR"
|
|
25
|
+
| "UNCLOSED_ELEMENT_ERROR"
|
|
26
|
+
| "RUBY_PARSE_ERROR"
|
|
27
|
+
|
|
28
|
+
export type SerializedErrorType = string
|
|
29
|
+
|
|
30
|
+
export function fromSerializedError(error: SerializedHerbError): HerbError {
|
|
31
|
+
switch (error.type) {
|
|
32
|
+
case "UNEXPECTED_ERROR": return UnexpectedError.from(error as SerializedUnexpectedError);
|
|
33
|
+
case "UNEXPECTED_TOKEN_ERROR": return UnexpectedTokenError.from(error as SerializedUnexpectedTokenError);
|
|
34
|
+
case "MISSING_OPENING_TAG_ERROR": return MissingOpeningTagError.from(error as SerializedMissingOpeningTagError);
|
|
35
|
+
case "MISSING_CLOSING_TAG_ERROR": return MissingClosingTagError.from(error as SerializedMissingClosingTagError);
|
|
36
|
+
case "TAG_NAMES_MISMATCH_ERROR": return TagNamesMismatchError.from(error as SerializedTagNamesMismatchError);
|
|
37
|
+
case "QUOTES_MISMATCH_ERROR": return QuotesMismatchError.from(error as SerializedQuotesMismatchError);
|
|
38
|
+
case "VOID_ELEMENT_CLOSING_TAG_ERROR": return VoidElementClosingTagError.from(error as SerializedVoidElementClosingTagError);
|
|
39
|
+
case "UNCLOSED_ELEMENT_ERROR": return UnclosedElementError.from(error as SerializedUnclosedElementError);
|
|
40
|
+
case "RUBY_PARSE_ERROR": return RubyParseError.from(error as SerializedRubyParseError);
|
|
41
|
+
|
|
42
|
+
default:
|
|
43
|
+
throw new Error(`Unknown node type: ${error.type}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface SerializedUnexpectedError {
|
|
48
|
+
type: "UNEXPECTED_ERROR";
|
|
49
|
+
message: string;
|
|
50
|
+
location: SerializedLocation;
|
|
51
|
+
description: string;
|
|
52
|
+
expected: string;
|
|
53
|
+
found: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface UnexpectedErrorProps {
|
|
57
|
+
type: string;
|
|
58
|
+
message: string;
|
|
59
|
+
location: Location;
|
|
60
|
+
description: string;
|
|
61
|
+
expected: string;
|
|
62
|
+
found: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export class UnexpectedError extends HerbError {
|
|
66
|
+
readonly description: string;
|
|
67
|
+
readonly expected: string;
|
|
68
|
+
readonly found: string;
|
|
69
|
+
|
|
70
|
+
static from(data: SerializedUnexpectedError): UnexpectedError {
|
|
71
|
+
return new UnexpectedError({
|
|
72
|
+
type: data.type,
|
|
73
|
+
message: data.message,
|
|
74
|
+
location: Location.from(data.location),
|
|
75
|
+
description: data.description,
|
|
76
|
+
expected: data.expected,
|
|
77
|
+
found: data.found,
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
constructor(props: UnexpectedErrorProps) {
|
|
82
|
+
super(props.type, props.message, props.location);
|
|
83
|
+
|
|
84
|
+
this.description = props.description;
|
|
85
|
+
this.expected = props.expected;
|
|
86
|
+
this.found = props.found;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
toJSON(): SerializedUnexpectedError {
|
|
90
|
+
return {
|
|
91
|
+
...super.toJSON(),
|
|
92
|
+
type: "UNEXPECTED_ERROR",
|
|
93
|
+
description: this.description,
|
|
94
|
+
expected: this.expected,
|
|
95
|
+
found: this.found,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
toDiagnostics(): HerbDiagnostic[] {
|
|
100
|
+
const diagnostics: HerbDiagnostic[] = [
|
|
101
|
+
{
|
|
102
|
+
line: this.location.start.line,
|
|
103
|
+
column: this.location.start.column,
|
|
104
|
+
endLine: this.location.end.line,
|
|
105
|
+
endColumn: this.location.end.column,
|
|
106
|
+
message: this.message,
|
|
107
|
+
severity: 'error'
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
// no-op for description
|
|
112
|
+
// no-op for expected
|
|
113
|
+
// no-op for found
|
|
114
|
+
|
|
115
|
+
return diagnostics
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
treeInspect(): string {
|
|
119
|
+
let output = "";
|
|
120
|
+
|
|
121
|
+
output += `@ UnexpectedError ${this.location.treeInspectWithLabel()}\n`;
|
|
122
|
+
output += `├── message: "${this.message}"\n`;
|
|
123
|
+
output += `├── description: ${JSON.stringify(this.description)}\n`;
|
|
124
|
+
output += `├── expected: ${JSON.stringify(this.expected)}\n`;
|
|
125
|
+
output += `└── found: ${JSON.stringify(this.found)}\n`;
|
|
126
|
+
|
|
127
|
+
return output;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface SerializedUnexpectedTokenError {
|
|
132
|
+
type: "UNEXPECTED_TOKEN_ERROR";
|
|
133
|
+
message: string;
|
|
134
|
+
location: SerializedLocation;
|
|
135
|
+
expected_type: string | null;
|
|
136
|
+
found: SerializedToken | null;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface UnexpectedTokenErrorProps {
|
|
140
|
+
type: string;
|
|
141
|
+
message: string;
|
|
142
|
+
location: Location;
|
|
143
|
+
expected_type: string | null;
|
|
144
|
+
found: Token | null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export class UnexpectedTokenError extends HerbError {
|
|
148
|
+
readonly expected_type: string | null;
|
|
149
|
+
readonly found: Token | null;
|
|
150
|
+
|
|
151
|
+
static from(data: SerializedUnexpectedTokenError): UnexpectedTokenError {
|
|
152
|
+
return new UnexpectedTokenError({
|
|
153
|
+
type: data.type,
|
|
154
|
+
message: data.message,
|
|
155
|
+
location: Location.from(data.location),
|
|
156
|
+
expected_type: data.expected_type,
|
|
157
|
+
found: data.found ? Token.from(data.found) : null,
|
|
158
|
+
})
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
constructor(props: UnexpectedTokenErrorProps) {
|
|
162
|
+
super(props.type, props.message, props.location);
|
|
163
|
+
|
|
164
|
+
this.expected_type = props.expected_type;
|
|
165
|
+
this.found = props.found;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
toJSON(): SerializedUnexpectedTokenError {
|
|
169
|
+
return {
|
|
170
|
+
...super.toJSON(),
|
|
171
|
+
type: "UNEXPECTED_TOKEN_ERROR",
|
|
172
|
+
expected_type: this.expected_type,
|
|
173
|
+
found: this.found ? this.found.toJSON() : null,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
toDiagnostics(): HerbDiagnostic[] {
|
|
178
|
+
const diagnostics: HerbDiagnostic[] = [
|
|
179
|
+
{
|
|
180
|
+
line: this.location.start.line,
|
|
181
|
+
column: this.location.start.column,
|
|
182
|
+
endLine: this.location.end.line,
|
|
183
|
+
endColumn: this.location.end.column,
|
|
184
|
+
message: this.message,
|
|
185
|
+
severity: 'error'
|
|
186
|
+
}
|
|
187
|
+
]
|
|
188
|
+
|
|
189
|
+
// no-op for expected_type
|
|
190
|
+
if (this.found) {
|
|
191
|
+
diagnostics.push({
|
|
192
|
+
line: this.found.location.start.line,
|
|
193
|
+
column: this.found.location.start.column,
|
|
194
|
+
endLine: this.found.location.end.line,
|
|
195
|
+
endColumn: this.found.location.end.column,
|
|
196
|
+
message: `found "${(this.found.value)}" is here`,
|
|
197
|
+
severity: 'info'
|
|
198
|
+
})
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
return diagnostics
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
treeInspect(): string {
|
|
206
|
+
let output = "";
|
|
207
|
+
|
|
208
|
+
output += `@ UnexpectedTokenError ${this.location.treeInspectWithLabel()}\n`;
|
|
209
|
+
output += `├── message: "${this.message}"\n`;
|
|
210
|
+
output += `├── expected_type: ${JSON.stringify(this.expected_type)}\n`;
|
|
211
|
+
output += `└── found: ${this.found ? this.found.treeInspect() : "∅"}\n`;
|
|
212
|
+
|
|
213
|
+
return output;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export interface SerializedMissingOpeningTagError {
|
|
218
|
+
type: "MISSING_OPENING_TAG_ERROR";
|
|
219
|
+
message: string;
|
|
220
|
+
location: SerializedLocation;
|
|
221
|
+
closing_tag: SerializedToken | null;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export interface MissingOpeningTagErrorProps {
|
|
225
|
+
type: string;
|
|
226
|
+
message: string;
|
|
227
|
+
location: Location;
|
|
228
|
+
closing_tag: Token | null;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export class MissingOpeningTagError extends HerbError {
|
|
232
|
+
readonly closing_tag: Token | null;
|
|
233
|
+
|
|
234
|
+
static from(data: SerializedMissingOpeningTagError): MissingOpeningTagError {
|
|
235
|
+
return new MissingOpeningTagError({
|
|
236
|
+
type: data.type,
|
|
237
|
+
message: data.message,
|
|
238
|
+
location: Location.from(data.location),
|
|
239
|
+
closing_tag: data.closing_tag ? Token.from(data.closing_tag) : null,
|
|
240
|
+
})
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
constructor(props: MissingOpeningTagErrorProps) {
|
|
244
|
+
super(props.type, props.message, props.location);
|
|
245
|
+
|
|
246
|
+
this.closing_tag = props.closing_tag;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
toJSON(): SerializedMissingOpeningTagError {
|
|
250
|
+
return {
|
|
251
|
+
...super.toJSON(),
|
|
252
|
+
type: "MISSING_OPENING_TAG_ERROR",
|
|
253
|
+
closing_tag: this.closing_tag ? this.closing_tag.toJSON() : null,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
toDiagnostics(): HerbDiagnostic[] {
|
|
258
|
+
const diagnostics: HerbDiagnostic[] = [
|
|
259
|
+
{
|
|
260
|
+
line: this.location.start.line,
|
|
261
|
+
column: this.location.start.column,
|
|
262
|
+
endLine: this.location.end.line,
|
|
263
|
+
endColumn: this.location.end.column,
|
|
264
|
+
message: this.message,
|
|
265
|
+
severity: 'error'
|
|
266
|
+
}
|
|
267
|
+
]
|
|
268
|
+
|
|
269
|
+
if (this.closing_tag) {
|
|
270
|
+
diagnostics.push({
|
|
271
|
+
line: this.closing_tag.location.start.line,
|
|
272
|
+
column: this.closing_tag.location.start.column,
|
|
273
|
+
endLine: this.closing_tag.location.end.line,
|
|
274
|
+
endColumn: this.closing_tag.location.end.column,
|
|
275
|
+
message: `closing_tag "${(this.closing_tag.value)}" is here`,
|
|
276
|
+
severity: 'info'
|
|
277
|
+
})
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
return diagnostics
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
treeInspect(): string {
|
|
285
|
+
let output = "";
|
|
286
|
+
|
|
287
|
+
output += `@ MissingOpeningTagError ${this.location.treeInspectWithLabel()}\n`;
|
|
288
|
+
output += `├── message: "${this.message}"\n`;
|
|
289
|
+
output += `└── closing_tag: ${this.closing_tag ? this.closing_tag.treeInspect() : "∅"}\n`;
|
|
290
|
+
|
|
291
|
+
return output;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export interface SerializedMissingClosingTagError {
|
|
296
|
+
type: "MISSING_CLOSING_TAG_ERROR";
|
|
297
|
+
message: string;
|
|
298
|
+
location: SerializedLocation;
|
|
299
|
+
opening_tag: SerializedToken | null;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export interface MissingClosingTagErrorProps {
|
|
303
|
+
type: string;
|
|
304
|
+
message: string;
|
|
305
|
+
location: Location;
|
|
306
|
+
opening_tag: Token | null;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export class MissingClosingTagError extends HerbError {
|
|
310
|
+
readonly opening_tag: Token | null;
|
|
311
|
+
|
|
312
|
+
static from(data: SerializedMissingClosingTagError): MissingClosingTagError {
|
|
313
|
+
return new MissingClosingTagError({
|
|
314
|
+
type: data.type,
|
|
315
|
+
message: data.message,
|
|
316
|
+
location: Location.from(data.location),
|
|
317
|
+
opening_tag: data.opening_tag ? Token.from(data.opening_tag) : null,
|
|
318
|
+
})
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
constructor(props: MissingClosingTagErrorProps) {
|
|
322
|
+
super(props.type, props.message, props.location);
|
|
323
|
+
|
|
324
|
+
this.opening_tag = props.opening_tag;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
toJSON(): SerializedMissingClosingTagError {
|
|
328
|
+
return {
|
|
329
|
+
...super.toJSON(),
|
|
330
|
+
type: "MISSING_CLOSING_TAG_ERROR",
|
|
331
|
+
opening_tag: this.opening_tag ? this.opening_tag.toJSON() : null,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
toDiagnostics(): HerbDiagnostic[] {
|
|
336
|
+
const diagnostics: HerbDiagnostic[] = [
|
|
337
|
+
{
|
|
338
|
+
line: this.location.start.line,
|
|
339
|
+
column: this.location.start.column,
|
|
340
|
+
endLine: this.location.end.line,
|
|
341
|
+
endColumn: this.location.end.column,
|
|
342
|
+
message: this.message,
|
|
343
|
+
severity: 'error'
|
|
344
|
+
}
|
|
345
|
+
]
|
|
346
|
+
|
|
347
|
+
if (this.opening_tag) {
|
|
348
|
+
diagnostics.push({
|
|
349
|
+
line: this.opening_tag.location.start.line,
|
|
350
|
+
column: this.opening_tag.location.start.column,
|
|
351
|
+
endLine: this.opening_tag.location.end.line,
|
|
352
|
+
endColumn: this.opening_tag.location.end.column,
|
|
353
|
+
message: `opening_tag "${(this.opening_tag.value)}" is here`,
|
|
354
|
+
severity: 'info'
|
|
355
|
+
})
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
return diagnostics
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
treeInspect(): string {
|
|
363
|
+
let output = "";
|
|
364
|
+
|
|
365
|
+
output += `@ MissingClosingTagError ${this.location.treeInspectWithLabel()}\n`;
|
|
366
|
+
output += `├── message: "${this.message}"\n`;
|
|
367
|
+
output += `└── opening_tag: ${this.opening_tag ? this.opening_tag.treeInspect() : "∅"}\n`;
|
|
368
|
+
|
|
369
|
+
return output;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
export interface SerializedTagNamesMismatchError {
|
|
374
|
+
type: "TAG_NAMES_MISMATCH_ERROR";
|
|
375
|
+
message: string;
|
|
376
|
+
location: SerializedLocation;
|
|
377
|
+
opening_tag: SerializedToken | null;
|
|
378
|
+
closing_tag: SerializedToken | null;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
export interface TagNamesMismatchErrorProps {
|
|
382
|
+
type: string;
|
|
383
|
+
message: string;
|
|
384
|
+
location: Location;
|
|
385
|
+
opening_tag: Token | null;
|
|
386
|
+
closing_tag: Token | null;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
export class TagNamesMismatchError extends HerbError {
|
|
390
|
+
readonly opening_tag: Token | null;
|
|
391
|
+
readonly closing_tag: Token | null;
|
|
392
|
+
|
|
393
|
+
static from(data: SerializedTagNamesMismatchError): TagNamesMismatchError {
|
|
394
|
+
return new TagNamesMismatchError({
|
|
395
|
+
type: data.type,
|
|
396
|
+
message: data.message,
|
|
397
|
+
location: Location.from(data.location),
|
|
398
|
+
opening_tag: data.opening_tag ? Token.from(data.opening_tag) : null,
|
|
399
|
+
closing_tag: data.closing_tag ? Token.from(data.closing_tag) : null,
|
|
400
|
+
})
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
constructor(props: TagNamesMismatchErrorProps) {
|
|
404
|
+
super(props.type, props.message, props.location);
|
|
405
|
+
|
|
406
|
+
this.opening_tag = props.opening_tag;
|
|
407
|
+
this.closing_tag = props.closing_tag;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
toJSON(): SerializedTagNamesMismatchError {
|
|
411
|
+
return {
|
|
412
|
+
...super.toJSON(),
|
|
413
|
+
type: "TAG_NAMES_MISMATCH_ERROR",
|
|
414
|
+
opening_tag: this.opening_tag ? this.opening_tag.toJSON() : null,
|
|
415
|
+
closing_tag: this.closing_tag ? this.closing_tag.toJSON() : null,
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
toDiagnostics(): HerbDiagnostic[] {
|
|
420
|
+
const diagnostics: HerbDiagnostic[] = [
|
|
421
|
+
{
|
|
422
|
+
line: this.location.start.line,
|
|
423
|
+
column: this.location.start.column,
|
|
424
|
+
endLine: this.location.end.line,
|
|
425
|
+
endColumn: this.location.end.column,
|
|
426
|
+
message: this.message,
|
|
427
|
+
severity: 'error'
|
|
428
|
+
}
|
|
429
|
+
]
|
|
430
|
+
|
|
431
|
+
if (this.opening_tag) {
|
|
432
|
+
diagnostics.push({
|
|
433
|
+
line: this.opening_tag.location.start.line,
|
|
434
|
+
column: this.opening_tag.location.start.column,
|
|
435
|
+
endLine: this.opening_tag.location.end.line,
|
|
436
|
+
endColumn: this.opening_tag.location.end.column,
|
|
437
|
+
message: `opening_tag "${(this.opening_tag.value)}" is here`,
|
|
438
|
+
severity: 'info'
|
|
439
|
+
})
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
if (this.closing_tag) {
|
|
443
|
+
diagnostics.push({
|
|
444
|
+
line: this.closing_tag.location.start.line,
|
|
445
|
+
column: this.closing_tag.location.start.column,
|
|
446
|
+
endLine: this.closing_tag.location.end.line,
|
|
447
|
+
endColumn: this.closing_tag.location.end.column,
|
|
448
|
+
message: `closing_tag "${(this.closing_tag.value)}" is here`,
|
|
449
|
+
severity: 'info'
|
|
450
|
+
})
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
return diagnostics
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
treeInspect(): string {
|
|
458
|
+
let output = "";
|
|
459
|
+
|
|
460
|
+
output += `@ TagNamesMismatchError ${this.location.treeInspectWithLabel()}\n`;
|
|
461
|
+
output += `├── message: "${this.message}"\n`;
|
|
462
|
+
output += `├── opening_tag: ${this.opening_tag ? this.opening_tag.treeInspect() : "∅"}\n`;
|
|
463
|
+
output += `└── closing_tag: ${this.closing_tag ? this.closing_tag.treeInspect() : "∅"}\n`;
|
|
464
|
+
|
|
465
|
+
return output;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
export interface SerializedQuotesMismatchError {
|
|
470
|
+
type: "QUOTES_MISMATCH_ERROR";
|
|
471
|
+
message: string;
|
|
472
|
+
location: SerializedLocation;
|
|
473
|
+
opening_quote: SerializedToken | null;
|
|
474
|
+
closing_quote: SerializedToken | null;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
export interface QuotesMismatchErrorProps {
|
|
478
|
+
type: string;
|
|
479
|
+
message: string;
|
|
480
|
+
location: Location;
|
|
481
|
+
opening_quote: Token | null;
|
|
482
|
+
closing_quote: Token | null;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
export class QuotesMismatchError extends HerbError {
|
|
486
|
+
readonly opening_quote: Token | null;
|
|
487
|
+
readonly closing_quote: Token | null;
|
|
488
|
+
|
|
489
|
+
static from(data: SerializedQuotesMismatchError): QuotesMismatchError {
|
|
490
|
+
return new QuotesMismatchError({
|
|
491
|
+
type: data.type,
|
|
492
|
+
message: data.message,
|
|
493
|
+
location: Location.from(data.location),
|
|
494
|
+
opening_quote: data.opening_quote ? Token.from(data.opening_quote) : null,
|
|
495
|
+
closing_quote: data.closing_quote ? Token.from(data.closing_quote) : null,
|
|
496
|
+
})
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
constructor(props: QuotesMismatchErrorProps) {
|
|
500
|
+
super(props.type, props.message, props.location);
|
|
501
|
+
|
|
502
|
+
this.opening_quote = props.opening_quote;
|
|
503
|
+
this.closing_quote = props.closing_quote;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
toJSON(): SerializedQuotesMismatchError {
|
|
507
|
+
return {
|
|
508
|
+
...super.toJSON(),
|
|
509
|
+
type: "QUOTES_MISMATCH_ERROR",
|
|
510
|
+
opening_quote: this.opening_quote ? this.opening_quote.toJSON() : null,
|
|
511
|
+
closing_quote: this.closing_quote ? this.closing_quote.toJSON() : null,
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
toDiagnostics(): HerbDiagnostic[] {
|
|
516
|
+
const diagnostics: HerbDiagnostic[] = [
|
|
517
|
+
{
|
|
518
|
+
line: this.location.start.line,
|
|
519
|
+
column: this.location.start.column,
|
|
520
|
+
endLine: this.location.end.line,
|
|
521
|
+
endColumn: this.location.end.column,
|
|
522
|
+
message: this.message,
|
|
523
|
+
severity: 'error'
|
|
524
|
+
}
|
|
525
|
+
]
|
|
526
|
+
|
|
527
|
+
if (this.opening_quote) {
|
|
528
|
+
diagnostics.push({
|
|
529
|
+
line: this.opening_quote.location.start.line,
|
|
530
|
+
column: this.opening_quote.location.start.column,
|
|
531
|
+
endLine: this.opening_quote.location.end.line,
|
|
532
|
+
endColumn: this.opening_quote.location.end.column,
|
|
533
|
+
message: `opening_quote "${(this.opening_quote.value)}" is here`,
|
|
534
|
+
severity: 'info'
|
|
535
|
+
})
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
if (this.closing_quote) {
|
|
539
|
+
diagnostics.push({
|
|
540
|
+
line: this.closing_quote.location.start.line,
|
|
541
|
+
column: this.closing_quote.location.start.column,
|
|
542
|
+
endLine: this.closing_quote.location.end.line,
|
|
543
|
+
endColumn: this.closing_quote.location.end.column,
|
|
544
|
+
message: `closing_quote "${(this.closing_quote.value)}" is here`,
|
|
545
|
+
severity: 'info'
|
|
546
|
+
})
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
return diagnostics
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
treeInspect(): string {
|
|
554
|
+
let output = "";
|
|
555
|
+
|
|
556
|
+
output += `@ QuotesMismatchError ${this.location.treeInspectWithLabel()}\n`;
|
|
557
|
+
output += `├── message: "${this.message}"\n`;
|
|
558
|
+
output += `├── opening_quote: ${this.opening_quote ? this.opening_quote.treeInspect() : "∅"}\n`;
|
|
559
|
+
output += `└── closing_quote: ${this.closing_quote ? this.closing_quote.treeInspect() : "∅"}\n`;
|
|
560
|
+
|
|
561
|
+
return output;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
export interface SerializedVoidElementClosingTagError {
|
|
566
|
+
type: "VOID_ELEMENT_CLOSING_TAG_ERROR";
|
|
567
|
+
message: string;
|
|
568
|
+
location: SerializedLocation;
|
|
569
|
+
tag_name: SerializedToken | null;
|
|
570
|
+
expected: string;
|
|
571
|
+
found: string;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
export interface VoidElementClosingTagErrorProps {
|
|
575
|
+
type: string;
|
|
576
|
+
message: string;
|
|
577
|
+
location: Location;
|
|
578
|
+
tag_name: Token | null;
|
|
579
|
+
expected: string;
|
|
580
|
+
found: string;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
export class VoidElementClosingTagError extends HerbError {
|
|
584
|
+
readonly tag_name: Token | null;
|
|
585
|
+
readonly expected: string;
|
|
586
|
+
readonly found: string;
|
|
587
|
+
|
|
588
|
+
static from(data: SerializedVoidElementClosingTagError): VoidElementClosingTagError {
|
|
589
|
+
return new VoidElementClosingTagError({
|
|
590
|
+
type: data.type,
|
|
591
|
+
message: data.message,
|
|
592
|
+
location: Location.from(data.location),
|
|
593
|
+
tag_name: data.tag_name ? Token.from(data.tag_name) : null,
|
|
594
|
+
expected: data.expected,
|
|
595
|
+
found: data.found,
|
|
596
|
+
})
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
constructor(props: VoidElementClosingTagErrorProps) {
|
|
600
|
+
super(props.type, props.message, props.location);
|
|
601
|
+
|
|
602
|
+
this.tag_name = props.tag_name;
|
|
603
|
+
this.expected = props.expected;
|
|
604
|
+
this.found = props.found;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
toJSON(): SerializedVoidElementClosingTagError {
|
|
608
|
+
return {
|
|
609
|
+
...super.toJSON(),
|
|
610
|
+
type: "VOID_ELEMENT_CLOSING_TAG_ERROR",
|
|
611
|
+
tag_name: this.tag_name ? this.tag_name.toJSON() : null,
|
|
612
|
+
expected: this.expected,
|
|
613
|
+
found: this.found,
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
toDiagnostics(): HerbDiagnostic[] {
|
|
618
|
+
const diagnostics: HerbDiagnostic[] = [
|
|
619
|
+
{
|
|
620
|
+
line: this.location.start.line,
|
|
621
|
+
column: this.location.start.column,
|
|
622
|
+
endLine: this.location.end.line,
|
|
623
|
+
endColumn: this.location.end.column,
|
|
624
|
+
message: this.message,
|
|
625
|
+
severity: 'error'
|
|
626
|
+
}
|
|
627
|
+
]
|
|
628
|
+
|
|
629
|
+
if (this.tag_name) {
|
|
630
|
+
diagnostics.push({
|
|
631
|
+
line: this.tag_name.location.start.line,
|
|
632
|
+
column: this.tag_name.location.start.column,
|
|
633
|
+
endLine: this.tag_name.location.end.line,
|
|
634
|
+
endColumn: this.tag_name.location.end.column,
|
|
635
|
+
message: `tag_name "${(this.tag_name.value)}" is here`,
|
|
636
|
+
severity: 'info'
|
|
637
|
+
})
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// no-op for expected
|
|
641
|
+
// no-op for found
|
|
642
|
+
|
|
643
|
+
return diagnostics
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
treeInspect(): string {
|
|
647
|
+
let output = "";
|
|
648
|
+
|
|
649
|
+
output += `@ VoidElementClosingTagError ${this.location.treeInspectWithLabel()}\n`;
|
|
650
|
+
output += `├── message: "${this.message}"\n`;
|
|
651
|
+
output += `├── tag_name: ${this.tag_name ? this.tag_name.treeInspect() : "∅"}\n`;
|
|
652
|
+
output += `├── expected: ${JSON.stringify(this.expected)}\n`;
|
|
653
|
+
output += `└── found: ${JSON.stringify(this.found)}\n`;
|
|
654
|
+
|
|
655
|
+
return output;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
export interface SerializedUnclosedElementError {
|
|
660
|
+
type: "UNCLOSED_ELEMENT_ERROR";
|
|
661
|
+
message: string;
|
|
662
|
+
location: SerializedLocation;
|
|
663
|
+
opening_tag: SerializedToken | null;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
export interface UnclosedElementErrorProps {
|
|
667
|
+
type: string;
|
|
668
|
+
message: string;
|
|
669
|
+
location: Location;
|
|
670
|
+
opening_tag: Token | null;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
export class UnclosedElementError extends HerbError {
|
|
674
|
+
readonly opening_tag: Token | null;
|
|
675
|
+
|
|
676
|
+
static from(data: SerializedUnclosedElementError): UnclosedElementError {
|
|
677
|
+
return new UnclosedElementError({
|
|
678
|
+
type: data.type,
|
|
679
|
+
message: data.message,
|
|
680
|
+
location: Location.from(data.location),
|
|
681
|
+
opening_tag: data.opening_tag ? Token.from(data.opening_tag) : null,
|
|
682
|
+
})
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
constructor(props: UnclosedElementErrorProps) {
|
|
686
|
+
super(props.type, props.message, props.location);
|
|
687
|
+
|
|
688
|
+
this.opening_tag = props.opening_tag;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
toJSON(): SerializedUnclosedElementError {
|
|
692
|
+
return {
|
|
693
|
+
...super.toJSON(),
|
|
694
|
+
type: "UNCLOSED_ELEMENT_ERROR",
|
|
695
|
+
opening_tag: this.opening_tag ? this.opening_tag.toJSON() : null,
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
toDiagnostics(): HerbDiagnostic[] {
|
|
700
|
+
const diagnostics: HerbDiagnostic[] = [
|
|
701
|
+
{
|
|
702
|
+
line: this.location.start.line,
|
|
703
|
+
column: this.location.start.column,
|
|
704
|
+
endLine: this.location.end.line,
|
|
705
|
+
endColumn: this.location.end.column,
|
|
706
|
+
message: this.message,
|
|
707
|
+
severity: 'error'
|
|
708
|
+
}
|
|
709
|
+
]
|
|
710
|
+
|
|
711
|
+
if (this.opening_tag) {
|
|
712
|
+
diagnostics.push({
|
|
713
|
+
line: this.opening_tag.location.start.line,
|
|
714
|
+
column: this.opening_tag.location.start.column,
|
|
715
|
+
endLine: this.opening_tag.location.end.line,
|
|
716
|
+
endColumn: this.opening_tag.location.end.column,
|
|
717
|
+
message: `opening_tag "${(this.opening_tag.value)}" is here`,
|
|
718
|
+
severity: 'info'
|
|
719
|
+
})
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
|
|
723
|
+
return diagnostics
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
treeInspect(): string {
|
|
727
|
+
let output = "";
|
|
728
|
+
|
|
729
|
+
output += `@ UnclosedElementError ${this.location.treeInspectWithLabel()}\n`;
|
|
730
|
+
output += `├── message: "${this.message}"\n`;
|
|
731
|
+
output += `└── opening_tag: ${this.opening_tag ? this.opening_tag.treeInspect() : "∅"}\n`;
|
|
732
|
+
|
|
733
|
+
return output;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
export interface SerializedRubyParseError {
|
|
738
|
+
type: "RUBY_PARSE_ERROR";
|
|
739
|
+
message: string;
|
|
740
|
+
location: SerializedLocation;
|
|
741
|
+
error_message: string;
|
|
742
|
+
diagnostic_id: string;
|
|
743
|
+
level: string;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
export interface RubyParseErrorProps {
|
|
747
|
+
type: string;
|
|
748
|
+
message: string;
|
|
749
|
+
location: Location;
|
|
750
|
+
error_message: string;
|
|
751
|
+
diagnostic_id: string;
|
|
752
|
+
level: string;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
export class RubyParseError extends HerbError {
|
|
756
|
+
readonly error_message: string;
|
|
757
|
+
readonly diagnostic_id: string;
|
|
758
|
+
readonly level: string;
|
|
759
|
+
|
|
760
|
+
static from(data: SerializedRubyParseError): RubyParseError {
|
|
761
|
+
return new RubyParseError({
|
|
762
|
+
type: data.type,
|
|
763
|
+
message: data.message,
|
|
764
|
+
location: Location.from(data.location),
|
|
765
|
+
error_message: data.error_message,
|
|
766
|
+
diagnostic_id: data.diagnostic_id,
|
|
767
|
+
level: data.level,
|
|
768
|
+
})
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
constructor(props: RubyParseErrorProps) {
|
|
772
|
+
super(props.type, props.message, props.location);
|
|
773
|
+
|
|
774
|
+
this.error_message = props.error_message;
|
|
775
|
+
this.diagnostic_id = props.diagnostic_id;
|
|
776
|
+
this.level = props.level;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
toJSON(): SerializedRubyParseError {
|
|
780
|
+
return {
|
|
781
|
+
...super.toJSON(),
|
|
782
|
+
type: "RUBY_PARSE_ERROR",
|
|
783
|
+
error_message: this.error_message,
|
|
784
|
+
diagnostic_id: this.diagnostic_id,
|
|
785
|
+
level: this.level,
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
toDiagnostics(): HerbDiagnostic[] {
|
|
790
|
+
const diagnostics: HerbDiagnostic[] = [
|
|
791
|
+
{
|
|
792
|
+
line: this.location.start.line,
|
|
793
|
+
column: this.location.start.column,
|
|
794
|
+
endLine: this.location.end.line,
|
|
795
|
+
endColumn: this.location.end.column,
|
|
796
|
+
message: this.message,
|
|
797
|
+
severity: 'error'
|
|
798
|
+
}
|
|
799
|
+
]
|
|
800
|
+
|
|
801
|
+
// no-op for error_message
|
|
802
|
+
// no-op for diagnostic_id
|
|
803
|
+
// no-op for level
|
|
804
|
+
|
|
805
|
+
return diagnostics
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
treeInspect(): string {
|
|
809
|
+
let output = "";
|
|
810
|
+
|
|
811
|
+
output += `@ RubyParseError ${this.location.treeInspectWithLabel()}\n`;
|
|
812
|
+
output += `├── message: "${this.message}"\n`;
|
|
813
|
+
output += `├── error_message: ${JSON.stringify(this.error_message)}\n`;
|
|
814
|
+
output += `├── diagnostic_id: ${JSON.stringify(this.diagnostic_id)}\n`;
|
|
815
|
+
output += `└── level: ${JSON.stringify(this.level)}\n`;
|
|
816
|
+
|
|
817
|
+
return output;
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
|