1use super::SourceLocation;
2use std::cell::RefCell;
3use std::fmt;
4use std::rc::Rc;
5
6#[derive(PartialEq, Eq, Debug)]
7pub enum CompilationErrorKind {
8 AbruptClosingOfEmptyComment,
9 CDataInHtmlContent,
10 DuplicateAttribute,
11 EndTagWithAttributes,
12 EndTagWithTrailingSolidus,
13 EofBeforeTagName,
14 EofInCdata,
15 EofInComment,
16 EofInScriptHtmlCommentLikeText,
17 EofInTag,
18 IncorrectlyClosedComment,
19 IncorrectlyOpenedComment,
20 InvalidFirstCharacterOfTagName,
21 MissingAttributeValue,
22 MissingEndTagName,
23 MissingWhitespaceBetweenAttributes,
24 NestedComment,
25 UnexpectedEqualsSignBeforeAttributeName,
26 UnexpectedCharacterInAttributeName,
27 UnexpectedCharacterInUnquotedAttributeValue,
28 UnexpectedNullCharacter, UnexpectedQuestionMarkInsteadOfTagName,
30 UnexpectedSolidusInTag,
31
32 InvalidEndTag,
34 MissingEndTag,
35 MissingInterpolationEnd,
36 MissingDynamicDirectiveArgumentEnd,
37 UnexpectedContentAfterDynamicDirective,
38 MissingDirectiveName,
39 MissingDirectiveArg,
40 MissingDirectiveMod,
41 InvalidVSlotModifier,
42
43 VIfNoExpression,
45 VIfSameKey,
46 VIfDuplicateDir,
47 VElseNoAdjacentIf,
48 VForNoExpression,
49 VForMalformedExpression,
50 VForTemplateKeyPlacement, VBindNoExpression,
52 VOnNoExpression,
53 VSlotUnexpectedDirectiveOnSlotOutlet,
54 VSlotMixedSlotUsage,
55 VSlotTemplateMisplaced,
56 VSlotDuplicateSlotNames,
57 VSlotExtraneousDefaultSlotChildren,
58 VSlotMisplaced,
59 VModelNoExpression,
61 VModelMalformedExpression,
62 VModelOnScopeVariable,
63 InvalidExpression,
64
65 UnexpectedDirExpression,
66 KeepAliveInvalidChildren,
67
68 PrefixIdNotSupported,
70 ModuleModeNotSupported,
71 CacheHandlerNotSupported,
72 ScopeIdNotSupported,
73
74 ExtendPoint,
77}
78
79pub struct CompilationError {
80 pub kind: CompilationErrorKind,
81 pub additional_message: Option<String>,
82 pub location: SourceLocation,
83}
84
85impl CompilationError {
86 pub fn new(kind: CompilationErrorKind) -> Self {
87 Self {
88 kind,
89 additional_message: None,
90 location: Default::default(),
91 }
92 }
93 pub fn with_location(mut self, loc: SourceLocation) -> Self {
94 self.location = loc;
95 self
96 }
97 pub fn with_additional_message(mut self, msg: String) -> Self {
98 self.additional_message = Some(msg);
99 self
100 }
101
102 fn msg(&self) -> &'static str {
103 msg(&self.kind)
104 }
105}
106
107#[cold]
108#[inline(never)]
109fn msg(kind: &CompilationErrorKind) -> &'static str {
110 use CompilationErrorKind::*;
111 match *kind {
112 AbruptClosingOfEmptyComment => "Illegal comment.",
113 CDataInHtmlContent => "CDATA section is allowed only in XML context.",
114 DuplicateAttribute => "Duplicate attribute.",
115 EndTagWithAttributes => "End tag cannot have attributes.",
116 EndTagWithTrailingSolidus => r#"Illegal "/" in tags."#,
117 EofBeforeTagName => "Unexpected EOF in tag.",
118 EofInCdata => "Unexpected EOF in CDATA section.",
119 EofInComment => "Unexpected EOF in comment.",
120 EofInScriptHtmlCommentLikeText => "Unexpected EOF in script.",
121 EofInTag => "Unexpected EOF in tag.",
122 IncorrectlyClosedComment => "Incorrectly closed comment.",
123 IncorrectlyOpenedComment => "Incorrectly opened comment.",
124 InvalidFirstCharacterOfTagName => "Illegal tag name. Use '<' to print '<'.",
125 UnexpectedEqualsSignBeforeAttributeName => "Attribute name was expected before '='.",
126 MissingAttributeValue => "Attribute value was expected.",
127 MissingEndTagName => "End tag name was expected.",
128 MissingWhitespaceBetweenAttributes => "Whitespace was expected.",
129 NestedComment => "Unexpected '<!--' in comment.",
130 UnexpectedCharacterInAttributeName =>
131 "Attribute name cannot contain U+0022 (\"), U+0027 ('), and U+003C (<).",
132 UnexpectedCharacterInUnquotedAttributeValue =>
133 "Unquoted attribute value cannot contain U+0022 (\"), U+0027 (\'), U+003C (<), U+003D (=), and U+0060 (`).",
134 UnexpectedQuestionMarkInsteadOfTagName => "'<?' is allowed only in XML context.",
135 UnexpectedNullCharacter => "Unexpected null character.",
136 UnexpectedSolidusInTag => "Illegal '/' in tags.",
137
138 InvalidEndTag => "Invalid end tag.",
140 MissingEndTag => "Element is missing end tag.",
141 MissingInterpolationEnd => "Interpolation end sign was not found.",
142 MissingDynamicDirectiveArgumentEnd =>
143 "End bracket for dynamic directive argument was not found. Note that dynamic directive argument cannot contain spaces.",
144 UnexpectedContentAfterDynamicDirective =>
145 "Unexpected content was found after a closed dynamic argument. Add a dot as separator if it is a modifier.",
146 MissingDirectiveName => "Legal directive name was expected.",
147 MissingDirectiveArg => "Directive argument was expected.",
148 MissingDirectiveMod => "Directive modifier was expected.",
149 InvalidVSlotModifier => "v-slot does not take modifier.",
150
151 VIfNoExpression => "v-if/v-else-if is missing expression.",
153 VIfSameKey => "v-if/else branches must use unique keys.",
154 VIfDuplicateDir => "Duplicate v-if/else-if/else. Use v-else-if instead.",
155 VElseNoAdjacentIf => "v-else/v-else-if has no adjacent v-if.",
156 VForNoExpression => "v-for is missing expression.",
157 VForMalformedExpression => "v-for has invalid expression.",
158 VForTemplateKeyPlacement => "<template v-for> key should be placed on the <template> tag.",
159 VBindNoExpression => "v-bind is missing expression.",
160 VOnNoExpression => "v-on is missing expression.",
161 VSlotUnexpectedDirectiveOnSlotOutlet => "Unexpected custom directive on <slot> outlet.",
162 VSlotMixedSlotUsage =>
163 "Mixed v-slot usage on both the component and nested <template>. When there are multiple named slots, all slots should use <template> syntax to avoid scope ambiguity.",
164 VSlotDuplicateSlotNames => "Duplicate slot names found. ",
165 VSlotExtraneousDefaultSlotChildren =>
166 r#"Extraneous children found when component already has explicitly named "default slot. These children will be ignored."#,
167 VSlotMisplaced => "v-slot can only be used on components or <template> tags.",
168 VSlotTemplateMisplaced => "<template v-slot> can only be used as a component's direct child.",
169 VModelNoExpression => "v-model is missing expression.",
170 VModelMalformedExpression => "v-model value must be a valid JavaScript member expression.",
171 VModelOnScopeVariable =>
172 "v-model cannot be used on v-for or v-slot scope variables because they are not writable.",
173 InvalidExpression => "Error parsing JavaScript expression: ",
174 UnexpectedDirExpression => "This directive does not accept any epxression.",
175 KeepAliveInvalidChildren => "<KeepAlive> expects exactly one child component.",
176
177 PrefixIdNotSupported =>
179 r#""prefixIdentifiers" option is not supported in this build of compiler."#,
180 ModuleModeNotSupported => "ES module mode is not supported in this build of compiler.",
181 CacheHandlerNotSupported =>
182 r#""cacheHandlers" option is only supported when the "prefixIdentifiers" option is enabled."#,
183 ScopeIdNotSupported => r#""scopeId" option is only supported in module mode."#,
184 ExtendPoint => "",
185 }
186}
187
188impl fmt::Display for CompilationError {
189 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190 if let Some(additional) = &self.additional_message {
191 write!(f, "{}{}", self.msg(), additional)
192 } else {
193 write!(f, "{}", self.msg())
194 }
195 }
196}
197
198pub trait ErrorHandler {
204 fn on_error(&self, _: CompilationError) {}
207}
208
209#[derive(Clone)]
210pub struct VecErrorHandler {
211 errors: Rc<RefCell<Vec<CompilationError>>>,
212}
213impl Default for VecErrorHandler {
214 fn default() -> Self {
215 Self {
216 errors: Rc::new(RefCell::new(vec![])),
217 }
218 }
219}
220
221impl ErrorHandler for VecErrorHandler {
222 fn on_error(&self, e: CompilationError) {
223 self.errors.borrow_mut().push(e);
224 }
225}
226
227#[cfg(test)]
228pub mod test {
229 use super::ErrorHandler;
230 #[derive(Clone)]
231 pub struct TestErrorHandler;
232 impl ErrorHandler for TestErrorHandler {}
233}