1use duck_diagnostic::{Diagnostic, DiagnosticCode, Severity};
16use serde::{Deserialize, Serialize};
17
18pub mod metadata;
19
20pub type DiagResult<T = ()> = Result<T, Diagnostic<Code>>;
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
49pub enum Code {
50 #[cfg(feature = "lexer")]
53 InvalidCharacter,
54 #[cfg(feature = "lexer")]
56 InvalidFrontMatter,
57 #[cfg(feature = "lexer")]
59 UnterminatedString,
60 #[cfg(feature = "lexer")]
62 UnterminatedExpression,
63 #[cfg(feature = "lexer")]
65 UnexpectedEof,
66 #[cfg(feature = "lexer")]
68 InvalidJsxSelfClosingTag,
69 #[cfg(feature = "lexer")]
71 UnterminatedJsxTag,
72 #[cfg(feature = "lexer")]
74 InvalidJsxClosingTag,
75 #[cfg(feature = "lexer")]
77 InvalidJsxAttribute,
78 #[cfg(feature = "lexer")]
80 UnterminatedCodeBlock,
81
82 #[cfg(feature = "lexer")]
84 EmptyFrontMatter,
85
86 #[cfg(feature = "parser")]
89 UnterminatedLink,
90 #[cfg(feature = "parser")]
92 UnterminatedImage,
93 #[cfg(feature = "parser")]
95 UnterminatedInlineCode,
96 #[cfg(feature = "parser")]
98 UnterminatedCodeBlockBlock,
99 #[cfg(feature = "parser")]
101 UnterminatedJsxOpenTag,
102 #[cfg(feature = "parser")]
104 UnterminatedJsxCloseTag,
105 #[cfg(feature = "parser")]
107 UnterminatedJsxExpression,
108 #[cfg(feature = "parser")]
110 UnterminatedMdComment,
111 #[cfg(feature = "parser")]
113 UnterminatedFrontmatter,
114 #[cfg(feature = "parser")]
116 MismatchedJsxCloseTag,
117 #[cfg(feature = "parser")]
119 TableShapeMismatch,
120 #[cfg(feature = "parser")]
122 StraySetextUnderline,
123 #[cfg(feature = "parser")]
125 MissingJsxAttributeValue,
126 #[cfg(feature = "parser")]
128 ListMarkerOverflow,
129 #[cfg(feature = "parser")]
133 BlockNestingTooDeep,
134
135 #[cfg(feature = "parser")]
137 EmptyFrontmatter,
138 #[cfg(feature = "parser")]
140 InvalidFrontmatterYaml,
141 #[cfg(feature = "parser")]
143 HeadingLevelClamped,
144 #[cfg(feature = "parser")]
146 RecoveredUnterminatedJsx,
147
148 #[cfg(feature = "transform")]
151 ImportFileNotFound,
152 #[cfg(feature = "transform")]
154 InvalidLineRange,
155 #[cfg(feature = "transform")]
157 RegistryIndexUnreadable,
158 #[cfg(feature = "transform")]
160 RegistryIndexMalformed,
161 #[cfg(feature = "transform")]
163 RegistryEntryNotFound,
164 #[cfg(feature = "transform")]
166 RegistrySourceUnreadable,
167 #[cfg(feature = "transform")]
169 ComponentSourceUnreadable,
170 #[cfg(feature = "transform")]
172 AssetCopyFailed,
173 #[cfg(feature = "transform")]
175 MermaidRenderFailed,
176
177 #[cfg(feature = "transform")]
179 MmdcUnavailable,
180 #[cfg(feature = "transform")]
182 MissingComponentAttr,
183 #[cfg(feature = "transform")]
185 AssetSourceMissing,
186 #[cfg(feature = "transform")]
190 BaseDirNotFound,
191
192 #[cfg(feature = "transform")]
196 KatexOpts,
197 #[cfg(feature = "transform")]
202 ThemeNotBundled,
203
204 #[cfg(feature = "codegen")]
207 MalformedJsxTagName,
208
209 #[cfg(feature = "codegen")]
212 MdxTableUnsupported,
213 #[cfg(feature = "codegen")]
216 HtmlExpressionDropped,
217
218 #[cfg(feature = "core")]
223 NoRootDir,
224 #[cfg(feature = "core")]
226 NoConfig,
227 #[cfg(feature = "core")]
229 NoCollections,
230 #[cfg(feature = "core")]
232 CollectionNotFound,
233 #[cfg(feature = "core")]
235 CollectionPatternNotFound,
236 #[cfg(feature = "core")]
238 CollectionSchemaNotFound,
239 #[cfg(feature = "core")]
241 InvalidConfig,
242 #[cfg(feature = "core")]
244 InvalidConfigPath,
245 #[cfg(feature = "core")]
247 ConfigExists,
248
249 IoRead,
255 IoWrite,
257 IoCreateDir,
259 JsonDeserialize,
261 JsonSerialize,
263 LockPoisoned,
265 IoRecoverable,
268
269 Custom { code: String, severity: Severity },
272}
273
274impl DiagnosticCode for Code {
275 fn code(&self) -> &str {
276 match self {
277 #[cfg(feature = "lexer")]
279 Self::InvalidCharacter => "E001",
280 #[cfg(feature = "lexer")]
281 Self::InvalidFrontMatter => "E002",
282 #[cfg(feature = "lexer")]
283 Self::UnterminatedString => "E003",
284 #[cfg(feature = "lexer")]
285 Self::UnterminatedExpression => "E004",
286 #[cfg(feature = "lexer")]
287 Self::UnexpectedEof => "E005",
288 #[cfg(feature = "lexer")]
289 Self::InvalidJsxSelfClosingTag => "E006",
290 #[cfg(feature = "lexer")]
291 Self::UnterminatedJsxTag => "E007",
292 #[cfg(feature = "lexer")]
293 Self::InvalidJsxClosingTag => "E008",
294 #[cfg(feature = "lexer")]
295 Self::InvalidJsxAttribute => "E009",
296 #[cfg(feature = "lexer")]
297 Self::UnterminatedCodeBlock => "E010",
298 #[cfg(feature = "lexer")]
299 Self::EmptyFrontMatter => "W001",
300
301 #[cfg(feature = "parser")]
303 Self::UnterminatedLink => "P001",
304 #[cfg(feature = "parser")]
305 Self::UnterminatedImage => "P002",
306 #[cfg(feature = "parser")]
307 Self::UnterminatedInlineCode => "P003",
308 #[cfg(feature = "parser")]
309 Self::UnterminatedCodeBlockBlock => "P004",
310 #[cfg(feature = "parser")]
311 Self::UnterminatedJsxOpenTag => "P005",
312 #[cfg(feature = "parser")]
313 Self::UnterminatedJsxCloseTag => "P006",
314 #[cfg(feature = "parser")]
315 Self::UnterminatedJsxExpression => "P007",
316 #[cfg(feature = "parser")]
317 Self::UnterminatedMdComment => "P008",
318 #[cfg(feature = "parser")]
319 Self::UnterminatedFrontmatter => "P009",
320 #[cfg(feature = "parser")]
321 Self::MismatchedJsxCloseTag => "P010",
322 #[cfg(feature = "parser")]
323 Self::TableShapeMismatch => "P011",
324 #[cfg(feature = "parser")]
325 Self::StraySetextUnderline => "P012",
326 #[cfg(feature = "parser")]
327 Self::MissingJsxAttributeValue => "P013",
328 #[cfg(feature = "parser")]
329 Self::ListMarkerOverflow => "P014",
330 #[cfg(feature = "parser")]
331 Self::BlockNestingTooDeep => "P015",
332 #[cfg(feature = "parser")]
333 Self::EmptyFrontmatter => "PW001",
334 #[cfg(feature = "parser")]
335 Self::InvalidFrontmatterYaml => "PW002",
336 #[cfg(feature = "parser")]
337 Self::HeadingLevelClamped => "PW003",
338 #[cfg(feature = "parser")]
339 Self::RecoveredUnterminatedJsx => "PW004",
340
341 #[cfg(feature = "transform")]
343 Self::ImportFileNotFound => "T001",
344 #[cfg(feature = "transform")]
345 Self::InvalidLineRange => "T002",
346 #[cfg(feature = "transform")]
347 Self::RegistryIndexUnreadable => "T003",
348 #[cfg(feature = "transform")]
349 Self::RegistryIndexMalformed => "T004",
350 #[cfg(feature = "transform")]
351 Self::RegistryEntryNotFound => "T005",
352 #[cfg(feature = "transform")]
353 Self::RegistrySourceUnreadable => "T006",
354 #[cfg(feature = "transform")]
355 Self::ComponentSourceUnreadable => "T007",
356 #[cfg(feature = "transform")]
357 Self::AssetCopyFailed => "T008",
358 #[cfg(feature = "transform")]
359 Self::MermaidRenderFailed => "T009",
360 #[cfg(feature = "transform")]
361 Self::MmdcUnavailable => "TW001",
362 #[cfg(feature = "transform")]
363 Self::MissingComponentAttr => "TW002",
364 #[cfg(feature = "transform")]
365 Self::AssetSourceMissing => "TW003",
366 #[cfg(feature = "transform")]
367 Self::BaseDirNotFound => "TW004",
368 #[cfg(feature = "transform")]
369 Self::ThemeNotBundled => "TW005",
370 #[cfg(feature = "transform")]
371 Self::KatexOpts => "TW006",
372
373 #[cfg(feature = "codegen")]
374 Self::MalformedJsxTagName => "G001",
375 #[cfg(feature = "codegen")]
376 Self::MdxTableUnsupported => "GW001",
377 #[cfg(feature = "codegen")]
378 Self::HtmlExpressionDropped => "GW002",
379
380 #[cfg(feature = "core")]
382 Self::NoRootDir => "C001",
383 #[cfg(feature = "core")]
384 Self::NoConfig => "C002",
385 #[cfg(feature = "core")]
386 Self::NoCollections => "C003",
387 #[cfg(feature = "core")]
388 Self::CollectionNotFound => "C004",
389 #[cfg(feature = "core")]
390 Self::CollectionPatternNotFound => "C005",
391 #[cfg(feature = "core")]
392 Self::CollectionSchemaNotFound => "C006",
393 #[cfg(feature = "core")]
394 Self::InvalidConfig => "C007",
395 #[cfg(feature = "core")]
396 Self::InvalidConfigPath => "C008",
397 #[cfg(feature = "core")]
398 Self::ConfigExists => "CW001",
399
400 Self::IoRead => "S001",
402 Self::IoWrite => "S002",
403 Self::IoCreateDir => "S003",
404 Self::JsonDeserialize => "S004",
405 Self::JsonSerialize => "S005",
406 Self::LockPoisoned => "S006",
407 Self::IoRecoverable => "SW001",
408
409 Self::Custom { code, .. } => code.as_str(),
410 }
411 }
412
413 fn severity(&self) -> Severity {
414 match self {
415 #[cfg(feature = "lexer")]
417 Self::InvalidCharacter
418 | Self::InvalidFrontMatter
419 | Self::UnterminatedString
420 | Self::UnterminatedExpression
421 | Self::UnexpectedEof
422 | Self::InvalidJsxSelfClosingTag
423 | Self::UnterminatedJsxTag
424 | Self::InvalidJsxClosingTag
425 | Self::InvalidJsxAttribute
426 | Self::UnterminatedCodeBlock => Severity::Error,
427 #[cfg(feature = "lexer")]
428 Self::EmptyFrontMatter => Severity::Warning,
429
430 #[cfg(feature = "parser")]
432 Self::UnterminatedLink
433 | Self::UnterminatedImage
434 | Self::UnterminatedInlineCode
435 | Self::UnterminatedCodeBlockBlock
436 | Self::UnterminatedJsxOpenTag
437 | Self::UnterminatedJsxCloseTag
438 | Self::UnterminatedJsxExpression
439 | Self::UnterminatedMdComment
440 | Self::UnterminatedFrontmatter
441 | Self::MismatchedJsxCloseTag
442 | Self::TableShapeMismatch
443 | Self::StraySetextUnderline
444 | Self::MissingJsxAttributeValue
445 | Self::ListMarkerOverflow
446 | Self::BlockNestingTooDeep => Severity::Error,
447 #[cfg(feature = "parser")]
448 Self::EmptyFrontmatter
449 | Self::InvalidFrontmatterYaml
450 | Self::HeadingLevelClamped
451 | Self::RecoveredUnterminatedJsx => Severity::Warning,
452
453 #[cfg(feature = "transform")]
455 Self::ImportFileNotFound
456 | Self::InvalidLineRange
457 | Self::RegistryIndexUnreadable
458 | Self::RegistryIndexMalformed
459 | Self::RegistryEntryNotFound
460 | Self::RegistrySourceUnreadable
461 | Self::ComponentSourceUnreadable
462 | Self::AssetCopyFailed
463 | Self::MermaidRenderFailed => Severity::Error,
464 #[cfg(feature = "transform")]
465 Self::MmdcUnavailable
466 | Self::MissingComponentAttr
467 | Self::AssetSourceMissing
468 | Self::BaseDirNotFound
469 | Self::ThemeNotBundled
470 | Self::KatexOpts => Severity::Warning,
471
472 #[cfg(feature = "codegen")]
473 Self::MalformedJsxTagName => Severity::Error,
474 #[cfg(feature = "codegen")]
475 Self::MdxTableUnsupported | Self::HtmlExpressionDropped => Severity::Warning,
476
477 #[cfg(feature = "core")]
479 Self::NoRootDir
480 | Self::NoConfig
481 | Self::NoCollections
482 | Self::CollectionNotFound
483 | Self::CollectionPatternNotFound
484 | Self::CollectionSchemaNotFound
485 | Self::InvalidConfig
486 | Self::InvalidConfigPath => Severity::Error,
487 #[cfg(feature = "core")]
488 Self::ConfigExists => Severity::Warning,
489
490 Self::IoRead
492 | Self::IoWrite
493 | Self::IoCreateDir
494 | Self::JsonDeserialize
495 | Self::JsonSerialize
496 | Self::LockPoisoned => Severity::Error,
497 Self::IoRecoverable => Severity::Warning,
498
499 Self::Custom { severity, .. } => *severity,
500 }
501 }
502}