diff options
Diffstat (limited to 'crates/ra_syntax/src/syntax_error.rs')
-rw-r--r-- | crates/ra_syntax/src/syntax_error.rs | 213 |
1 files changed, 24 insertions, 189 deletions
diff --git a/crates/ra_syntax/src/syntax_error.rs b/crates/ra_syntax/src/syntax_error.rs index 7f9d36618..54acf7847 100644 --- a/crates/ra_syntax/src/syntax_error.rs +++ b/crates/ra_syntax/src/syntax_error.rs | |||
@@ -1,209 +1,44 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! See docs for `SyntaxError`. |
2 | 2 | ||
3 | use std::fmt; | 3 | use std::fmt; |
4 | 4 | ||
5 | use ra_parser::ParseError; | 5 | use crate::{TextRange, TextUnit}; |
6 | |||
7 | use crate::{validation::EscapeError, TextRange, TextUnit, TokenizeError}; | ||
8 | 6 | ||
7 | /// Represents the result of unsuccessful tokenization, parsing | ||
8 | /// or tree validation. | ||
9 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 9 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
10 | pub struct SyntaxError { | 10 | pub struct SyntaxError(String, TextRange); |
11 | kind: SyntaxErrorKind, | 11 | |
12 | location: Location, | 12 | // FIXME: there was an unused SyntaxErrorKind previously (before this enum was removed) |
13 | } | 13 | // It was introduced in this PR: https://github.com/rust-analyzer/rust-analyzer/pull/846/files#diff-827da9b03b8f9faa1bade5cdd44d5dafR95 |
14 | 14 | // but it was not removed by a mistake. | |
15 | // FIXME: Location should be just `Location(TextRange)` | 15 | // |
16 | // TextUnit enum member just unnecessarily compicates things, | 16 | // So, we need to find a place where to stick validation for attributes in match clauses. |
17 | // we should'n treat it specially, it just as a `TextRange { start: x, end: x + 1 }` | 17 | // Code before refactor: |
18 | // see `location_to_range()` in ra_ide/src/diagnostics | 18 | // InvalidMatchInnerAttr => { |
19 | #[derive(Clone, PartialEq, Eq, Hash)] | 19 | // write!(f, "Inner attributes are only allowed directly after the opening brace of the match expression") |
20 | pub enum Location { | 20 | // } |
21 | Offset(TextUnit), | ||
22 | Range(TextRange), | ||
23 | } | ||
24 | |||
25 | impl From<TextUnit> for Location { | ||
26 | fn from(offset: TextUnit) -> Location { | ||
27 | Location::Offset(offset) | ||
28 | } | ||
29 | } | ||
30 | |||
31 | impl From<TextRange> for Location { | ||
32 | fn from(range: TextRange) -> Location { | ||
33 | Location::Range(range) | ||
34 | } | ||
35 | } | ||
36 | |||
37 | impl fmt::Debug for Location { | ||
38 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
39 | match self { | ||
40 | Location::Offset(it) => fmt::Debug::fmt(it, f), | ||
41 | Location::Range(it) => fmt::Debug::fmt(it, f), | ||
42 | } | ||
43 | } | ||
44 | } | ||
45 | 21 | ||
46 | impl SyntaxError { | 22 | impl SyntaxError { |
47 | pub fn new<L: Into<Location>>(kind: SyntaxErrorKind, loc: L) -> SyntaxError { | 23 | pub fn new(message: impl Into<String>, range: TextRange) -> Self { |
48 | SyntaxError { kind, location: loc.into() } | 24 | Self(message.into(), range) |
49 | } | 25 | } |
50 | 26 | pub fn new_at_offset(message: impl Into<String>, offset: TextUnit) -> Self { | |
51 | pub fn kind(&self) -> SyntaxErrorKind { | 27 | Self(message.into(), TextRange::offset_len(offset, 0.into())) |
52 | self.kind.clone() | ||
53 | } | 28 | } |
54 | 29 | ||
55 | pub fn location(&self) -> Location { | 30 | pub fn range(&self) -> TextRange { |
56 | self.location.clone() | 31 | self.1 |
57 | } | 32 | } |
58 | 33 | ||
59 | pub fn offset(&self) -> TextUnit { | 34 | pub fn with_range(mut self, range: TextRange) -> Self { |
60 | match self.location { | 35 | self.1 = range; |
61 | Location::Offset(offset) => offset, | ||
62 | Location::Range(range) => range.start(), | ||
63 | } | ||
64 | } | ||
65 | |||
66 | pub fn add_offset(mut self, plus_offset: TextUnit, minus_offset: TextUnit) -> SyntaxError { | ||
67 | self.location = match self.location { | ||
68 | Location::Range(range) => Location::Range(range + plus_offset - minus_offset), | ||
69 | Location::Offset(offset) => Location::Offset(offset + plus_offset - minus_offset), | ||
70 | }; | ||
71 | |||
72 | self | 36 | self |
73 | } | 37 | } |
74 | |||
75 | pub fn debug_dump(&self, acc: &mut impl fmt::Write) { | ||
76 | writeln!(acc, "error {:?}: {}", self.location(), self.kind()).unwrap(); | ||
77 | } | ||
78 | } | 38 | } |
79 | 39 | ||
80 | impl fmt::Display for SyntaxError { | 40 | impl fmt::Display for SyntaxError { |
81 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 41 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
82 | self.kind.fmt(f) | 42 | self.0.fmt(f) |
83 | } | ||
84 | } | ||
85 | |||
86 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
87 | pub enum SyntaxErrorKind { | ||
88 | ParseError(ParseError), | ||
89 | EscapeError(EscapeError), | ||
90 | TokenizeError(TokenizeError), | ||
91 | // FIXME: the obvious pattern of this enum dictates that the following enum variants | ||
92 | // should be wrapped into something like `SemmanticError(SemmanticError)` | ||
93 | // or `ValidateError(ValidateError)` or `SemmanticValidateError(...)` | ||
94 | InvalidBlockAttr, | ||
95 | InvalidMatchInnerAttr, | ||
96 | InvalidTupleIndexFormat, | ||
97 | VisibilityNotAllowed, | ||
98 | InclusiveRangeMissingEnd, | ||
99 | } | ||
100 | |||
101 | impl fmt::Display for SyntaxErrorKind { | ||
102 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
103 | use self::SyntaxErrorKind::*; | ||
104 | match self { | ||
105 | InvalidBlockAttr => { | ||
106 | write!(f, "A block in this position cannot accept inner attributes") | ||
107 | } | ||
108 | InvalidMatchInnerAttr => { | ||
109 | write!(f, "Inner attributes are only allowed directly after the opening brace of the match expression") | ||
110 | } | ||
111 | InvalidTupleIndexFormat => { | ||
112 | write!(f, "Tuple (struct) field access is only allowed through decimal integers with no underscores or suffix") | ||
113 | } | ||
114 | ParseError(msg) => write!(f, "{}", msg.0), | ||
115 | EscapeError(err) => write!(f, "{}", err), | ||
116 | TokenizeError(err) => write!(f, "{}", err), | ||
117 | VisibilityNotAllowed => { | ||
118 | write!(f, "unnecessary visibility qualifier") | ||
119 | } | ||
120 | InclusiveRangeMissingEnd => { | ||
121 | write!(f, "An inclusive range must have an end expression") | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | } | ||
126 | |||
127 | impl fmt::Display for TokenizeError { | ||
128 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
129 | #[rustfmt::skip] | ||
130 | let msg = match self { | ||
131 | TokenizeError::EmptyInt => { | ||
132 | "Missing digits after the integer base prefix" | ||
133 | } | ||
134 | TokenizeError::EmptyExponent => { | ||
135 | "Missing digits after the exponent symbol" | ||
136 | } | ||
137 | TokenizeError::UnterminatedBlockComment => { | ||
138 | "Missing trailing `*/` symbols to terminate the block comment" | ||
139 | } | ||
140 | TokenizeError::UnterminatedChar => { | ||
141 | "Missing trailing `'` symbol to terminate the character literal" | ||
142 | } | ||
143 | TokenizeError::UnterminatedByte => { | ||
144 | "Missing trailing `'` symbol to terminate the byte literal" | ||
145 | } | ||
146 | TokenizeError::UnterminatedString => { | ||
147 | "Missing trailing `\"` symbol to terminate the string literal" | ||
148 | } | ||
149 | TokenizeError::UnterminatedByteString => { | ||
150 | "Missing trailing `\"` symbol to terminate the byte string literal" | ||
151 | } | ||
152 | TokenizeError::UnterminatedRawString => { | ||
153 | "Missing trailing `\"` with `#` symbols to terminate the raw string literal" | ||
154 | } | ||
155 | TokenizeError::UnterminatedRawByteString => { | ||
156 | "Missing trailing `\"` with `#` symbols to terminate the raw byte string literal" | ||
157 | } | ||
158 | TokenizeError::UnstartedRawString => { | ||
159 | "Missing `\"` symbol after `#` symbols to begin the raw string literal" | ||
160 | } | ||
161 | TokenizeError::UnstartedRawByteString => { | ||
162 | "Missing `\"` symbol after `#` symbols to begin the raw byte string literal" | ||
163 | } | ||
164 | TokenizeError::LifetimeStartsWithNumber => { | ||
165 | "Lifetime name cannot start with a number" | ||
166 | } | ||
167 | }; | ||
168 | write!(f, "{}", msg) | ||
169 | } | ||
170 | } | ||
171 | |||
172 | impl fmt::Display for EscapeError { | ||
173 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
174 | let msg = match self { | ||
175 | EscapeError::ZeroChars => "Empty literal", | ||
176 | EscapeError::MoreThanOneChar => "Literal should be one character long", | ||
177 | EscapeError::LoneSlash => "Character must be escaped: '\\'", | ||
178 | EscapeError::InvalidEscape => "Invalid escape sequence", | ||
179 | EscapeError::BareCarriageReturn => "Character must be escaped: '\r'", | ||
180 | EscapeError::EscapeOnlyChar => "Character must be escaped", | ||
181 | EscapeError::TooShortHexEscape => "Escape sequence should have two digits", | ||
182 | EscapeError::InvalidCharInHexEscape => "Escape sequence should be a hexadecimal number", | ||
183 | EscapeError::OutOfRangeHexEscape => "Escape sequence should be ASCII", | ||
184 | EscapeError::NoBraceInUnicodeEscape => "Invalid escape sequence", | ||
185 | EscapeError::InvalidCharInUnicodeEscape => "Invalid escape sequence", | ||
186 | EscapeError::EmptyUnicodeEscape => "Invalid escape sequence", | ||
187 | EscapeError::UnclosedUnicodeEscape => "Missing '}'", | ||
188 | EscapeError::LeadingUnderscoreUnicodeEscape => "Invalid escape sequence", | ||
189 | EscapeError::OverlongUnicodeEscape => { | ||
190 | "Unicode escape sequence should have at most 6 digits" | ||
191 | } | ||
192 | EscapeError::LoneSurrogateUnicodeEscape => { | ||
193 | "Unicode escape code should not be a surrogate" | ||
194 | } | ||
195 | EscapeError::OutOfRangeUnicodeEscape => { | ||
196 | "Unicode escape code should be at most 0x10FFFF" | ||
197 | } | ||
198 | EscapeError::UnicodeEscapeInByte => "Unicode escapes are not allowed in bytes", | ||
199 | EscapeError::NonAsciiCharInByte => "Non ASCII characters are not allowed in bytes", | ||
200 | }; | ||
201 | write!(f, "{}", msg) | ||
202 | } | ||
203 | } | ||
204 | |||
205 | impl From<EscapeError> for SyntaxErrorKind { | ||
206 | fn from(err: EscapeError) -> Self { | ||
207 | SyntaxErrorKind::EscapeError(err) | ||
208 | } | 43 | } |
209 | } | 44 | } |