diff options
Diffstat (limited to 'crates/ra_syntax/src/syntax_node/syntax_error.rs')
-rw-r--r-- | crates/ra_syntax/src/syntax_node/syntax_error.rs | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/syntax_node/syntax_error.rs b/crates/ra_syntax/src/syntax_node/syntax_error.rs new file mode 100644 index 000000000..412cf82cc --- /dev/null +++ b/crates/ra_syntax/src/syntax_node/syntax_error.rs | |||
@@ -0,0 +1,142 @@ | |||
1 | use std::fmt; | ||
2 | |||
3 | use crate::{TextRange, TextUnit}; | ||
4 | |||
5 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
6 | pub struct SyntaxError { | ||
7 | kind: SyntaxErrorKind, | ||
8 | location: Location, | ||
9 | } | ||
10 | |||
11 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
12 | pub enum Location { | ||
13 | Offset(TextUnit), | ||
14 | Range(TextRange), | ||
15 | } | ||
16 | |||
17 | impl Into<Location> for TextUnit { | ||
18 | fn into(self) -> Location { | ||
19 | Location::Offset(self) | ||
20 | } | ||
21 | } | ||
22 | |||
23 | impl Into<Location> for TextRange { | ||
24 | fn into(self) -> Location { | ||
25 | Location::Range(self) | ||
26 | } | ||
27 | } | ||
28 | |||
29 | impl SyntaxError { | ||
30 | pub fn new<L: Into<Location>>(kind: SyntaxErrorKind, loc: L) -> SyntaxError { | ||
31 | SyntaxError { kind, location: loc.into() } | ||
32 | } | ||
33 | |||
34 | pub fn kind(&self) -> SyntaxErrorKind { | ||
35 | self.kind.clone() | ||
36 | } | ||
37 | |||
38 | pub fn location(&self) -> Location { | ||
39 | self.location.clone() | ||
40 | } | ||
41 | |||
42 | pub fn offset(&self) -> TextUnit { | ||
43 | match self.location { | ||
44 | Location::Offset(offset) => offset, | ||
45 | Location::Range(range) => range.start(), | ||
46 | } | ||
47 | } | ||
48 | |||
49 | pub fn add_offset(mut self, plus_offset: TextUnit) -> SyntaxError { | ||
50 | self.location = match self.location { | ||
51 | Location::Range(range) => Location::Range(range + plus_offset), | ||
52 | Location::Offset(offset) => Location::Offset(offset + plus_offset), | ||
53 | }; | ||
54 | |||
55 | self | ||
56 | } | ||
57 | } | ||
58 | |||
59 | impl fmt::Display for SyntaxError { | ||
60 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
61 | self.kind.fmt(f) | ||
62 | } | ||
63 | } | ||
64 | |||
65 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
66 | pub enum SyntaxErrorKind { | ||
67 | ParseError(ParseError), | ||
68 | UnescapedCodepoint, | ||
69 | EmptyChar, | ||
70 | UnclosedChar, | ||
71 | OverlongChar, | ||
72 | EmptyByte, | ||
73 | UnclosedByte, | ||
74 | OverlongByte, | ||
75 | ByteOutOfRange, | ||
76 | UnescapedByte, | ||
77 | EmptyByteEscape, | ||
78 | InvalidByteEscape, | ||
79 | TooShortByteCodeEscape, | ||
80 | MalformedByteCodeEscape, | ||
81 | UnicodeEscapeForbidden, | ||
82 | EmptyAsciiEscape, | ||
83 | InvalidAsciiEscape, | ||
84 | TooShortAsciiCodeEscape, | ||
85 | AsciiCodeEscapeOutOfRange, | ||
86 | MalformedAsciiCodeEscape, | ||
87 | UnclosedUnicodeEscape, | ||
88 | MalformedUnicodeEscape, | ||
89 | EmptyUnicodeEcape, | ||
90 | OverlongUnicodeEscape, | ||
91 | UnicodeEscapeOutOfRange, | ||
92 | UnclosedString, | ||
93 | InvalidSuffix, | ||
94 | InvalidBlockAttr, | ||
95 | } | ||
96 | |||
97 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
98 | pub struct ParseError(pub String); | ||
99 | |||
100 | impl fmt::Display for SyntaxErrorKind { | ||
101 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
102 | use self::SyntaxErrorKind::*; | ||
103 | match self { | ||
104 | UnescapedCodepoint => write!(f, "This codepoint should always be escaped"), | ||
105 | EmptyAsciiEscape => write!(f, "Empty escape sequence"), | ||
106 | InvalidAsciiEscape => write!(f, "Invalid escape sequence"), | ||
107 | EmptyChar => write!(f, "Empty char literal"), | ||
108 | UnclosedChar => write!(f, "Unclosed char literal"), | ||
109 | OverlongChar => write!(f, "Char literal should be one character long"), | ||
110 | EmptyByte => write!(f, "Empty byte literal"), | ||
111 | UnclosedByte => write!(f, "Unclosed byte literal"), | ||
112 | OverlongByte => write!(f, "Byte literal should be one character long"), | ||
113 | ByteOutOfRange => write!(f, "Byte should be a valid ASCII character"), | ||
114 | UnescapedByte => write!(f, "This byte should always be escaped"), | ||
115 | EmptyByteEscape => write!(f, "Empty escape sequence"), | ||
116 | InvalidByteEscape => write!(f, "Invalid escape sequence"), | ||
117 | TooShortByteCodeEscape => write!(f, "Escape sequence should have two digits"), | ||
118 | MalformedByteCodeEscape => write!(f, "Escape sequence should be a hexadecimal number"), | ||
119 | UnicodeEscapeForbidden => { | ||
120 | write!(f, "Unicode escapes are not allowed in byte literals or byte strings") | ||
121 | } | ||
122 | TooShortAsciiCodeEscape => write!(f, "Escape sequence should have two digits"), | ||
123 | AsciiCodeEscapeOutOfRange => { | ||
124 | write!(f, "Escape sequence should be between \\x00 and \\x7F") | ||
125 | } | ||
126 | MalformedAsciiCodeEscape => write!(f, "Escape sequence should be a hexadecimal number"), | ||
127 | UnclosedUnicodeEscape => write!(f, "Missing `}}`"), | ||
128 | MalformedUnicodeEscape => write!(f, "Malformed unicode escape sequence"), | ||
129 | EmptyUnicodeEcape => write!(f, "Empty unicode escape sequence"), | ||
130 | OverlongUnicodeEscape => { | ||
131 | write!(f, "Unicode escape sequence should have at most 6 digits") | ||
132 | } | ||
133 | UnicodeEscapeOutOfRange => write!(f, "Unicode escape code should be at most 0x10FFFF"), | ||
134 | UnclosedString => write!(f, "Unclosed string literal"), | ||
135 | InvalidSuffix => write!(f, "Invalid literal suffix"), | ||
136 | InvalidBlockAttr => { | ||
137 | write!(f, "A block in this position cannot accept inner attributes") | ||
138 | } | ||
139 | ParseError(msg) => write!(f, "{}", msg.0), | ||
140 | } | ||
141 | } | ||
142 | } | ||