1use std::{borrow::Cow, error::Error, fmt};
2
3#[derive(Clone, Debug)]
4pub struct SyntaxError {
6 pub kind: SyntaxErrorKind,
7 pub pos: usize,
8 pub line: usize,
9 pub column: usize,
10}
11
12#[derive(Clone, Debug)]
13pub enum SyntaxErrorKind {
14 ExpectAngularBlock(&'static str),
15 ExpectAngularLet,
16 ExpectAngularSwitch,
17 ExpectAstroAttr,
18 ExpectAstroExpr,
19 ExpectAttrName,
20 ExpectAttrValue,
21 ExpectCdata,
22 ExpectChar(char),
23 ExpectCloseTag {
24 tag_name: String,
25 line: usize,
26 column: usize,
27 },
28 ExpectComment,
29 ExpectDoctype,
30 ExpectElement,
31 ExpectFrontMatter,
32 ExpectIdentifier,
33 ExpectJinjaBlockEnd,
34 ExpectJinjaTag,
35 ExpectKeyword(&'static str),
36 ExpectMustacheInterpolation,
37 ExpectSelfCloseTag,
38 ExpectSvelteAttachment,
39 ExpectSvelteAtTag,
40 ExpectSvelteAttr,
41 ExpectSvelteAwaitBlock,
42 ExpectSvelteBlockEnd,
43 ExpectSvelteCatchBlock,
44 ExpectSvelteEachBlock,
45 ExpectSvelteElseIfBlock,
46 ExpectSvelteIfBlock,
47 ExpectSvelteInterpolation,
48 ExpectSvelteKeyBlock,
49 ExpectSvelteSnippetBlock,
50 ExpectSvelteThenBlock,
51 ExpectTagName,
52 ExpectTextNode,
53 ExpectVentoBlockEnd,
54 ExpectVueDirective,
55 ExpectXmlDecl,
56}
57
58impl fmt::Display for SyntaxErrorKind {
59 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60 let reason: Cow<_> = match self {
61 SyntaxErrorKind::ExpectAngularBlock(keyword) => {
62 format!("expected Angular `@{keyword}` block").into()
63 }
64 SyntaxErrorKind::ExpectAngularLet => "expected Angular `@let`".into(),
65 SyntaxErrorKind::ExpectAngularSwitch => "expected Angular `@switch`".into(),
66 SyntaxErrorKind::ExpectAstroAttr => "expected Astro attribute".into(),
67 SyntaxErrorKind::ExpectAstroExpr => "expected Astro expression".into(),
68 SyntaxErrorKind::ExpectAttrName => "expected attribute name".into(),
69 SyntaxErrorKind::ExpectAttrValue => "expected attribute value".into(),
70 SyntaxErrorKind::ExpectCdata => "expected CDATA section".into(),
71 SyntaxErrorKind::ExpectChar(c) => format!("expected char '{c}'").into(),
72 SyntaxErrorKind::ExpectCloseTag {
73 tag_name,
74 line,
75 column,
76 } => format!(
77 "expected close tag for opening tag <{tag_name}> from line {line}, column {column}"
78 )
79 .into(),
80 SyntaxErrorKind::ExpectComment => "expected comment".into(),
81 SyntaxErrorKind::ExpectDoctype => "expected HTML doctype".into(),
82 SyntaxErrorKind::ExpectElement => "expected element".into(),
83 SyntaxErrorKind::ExpectFrontMatter => "expected front matter".into(),
84 SyntaxErrorKind::ExpectIdentifier => "expected identifier".into(),
85 SyntaxErrorKind::ExpectJinjaBlockEnd => "expected Jinja block end".into(),
86 SyntaxErrorKind::ExpectJinjaTag => "expected Jinja tag".into(),
87 SyntaxErrorKind::ExpectKeyword(keyword) => {
88 format!("expected keyword '{keyword}'").into()
89 }
90 SyntaxErrorKind::ExpectMustacheInterpolation => {
91 "expected mustache-like interpolation".into()
92 }
93 SyntaxErrorKind::ExpectSelfCloseTag => "expected self close tag".into(),
94 SyntaxErrorKind::ExpectSvelteAttachment => "expected Svelte attachment".into(),
95 SyntaxErrorKind::ExpectSvelteAtTag => "expected Svelte `{@` tag".into(),
96 SyntaxErrorKind::ExpectSvelteAttr => "expected Svelte attribute".into(),
97 SyntaxErrorKind::ExpectSvelteAwaitBlock => "expected Svelte await block".into(),
98 SyntaxErrorKind::ExpectSvelteBlockEnd => "expected end of Svelte block".into(),
99 SyntaxErrorKind::ExpectSvelteCatchBlock => "expected Svelte catch block".into(),
100 SyntaxErrorKind::ExpectSvelteEachBlock => "expected Svelte each block".into(),
101 SyntaxErrorKind::ExpectSvelteElseIfBlock => "expected Svelte else if block".into(),
102 SyntaxErrorKind::ExpectSvelteIfBlock => "expected Svelte if block".into(),
103 SyntaxErrorKind::ExpectSvelteInterpolation => "expected Svelte interpolation".into(),
104 SyntaxErrorKind::ExpectSvelteKeyBlock => "expected Svelte key block".into(),
105 SyntaxErrorKind::ExpectSvelteSnippetBlock => "expected Svelte snippet block".into(),
106 SyntaxErrorKind::ExpectSvelteThenBlock => "expected Svelte then block".into(),
107 SyntaxErrorKind::ExpectTagName => "expected tag name".into(),
108 SyntaxErrorKind::ExpectTextNode => "expected text node".into(),
109 SyntaxErrorKind::ExpectVentoBlockEnd => "expected Vento block end".into(),
110 SyntaxErrorKind::ExpectVueDirective => "expected Vue directive".into(),
111 SyntaxErrorKind::ExpectXmlDecl => "expected XML declaration".into(),
112 };
113
114 write!(f, "{reason}")
115 }
116}
117
118impl fmt::Display for SyntaxError {
119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120 write!(
121 f,
122 "syntax error '{}' at line {}, column {}",
123 self.kind, self.line, self.column
124 )
125 }
126}
127
128impl Error for SyntaxError {}
129
130#[derive(Debug)]
131pub enum FormatError<E> {
133 Syntax(SyntaxError),
135 External(Vec<E>),
138}
139
140impl<E> fmt::Display for FormatError<E>
141where
142 E: fmt::Display,
143{
144 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145 match self {
146 FormatError::Syntax(e) => e.fmt(f),
147 FormatError::External(errors) => {
148 writeln!(f, "failed to format code with external formatter:")?;
149 for error in errors {
150 writeln!(f, "{error}")?;
151 }
152 Ok(())
153 }
154 }
155 }
156}
157
158impl<E> Error for FormatError<E> where E: Error {}