diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_assists/src/introduce_variable.rs | 5 | ||||
-rw-r--r-- | crates/ra_lsp_server/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/conv.rs | 150 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 6 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/world.rs | 6 | ||||
-rw-r--r-- | crates/ra_lsp_server/tests/heavy_tests/main.rs | 48 | ||||
-rw-r--r-- | crates/ra_syntax/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/ra_syntax/src/parsing/lexer.rs | 136 | ||||
-rw-r--r-- | crates/ra_syntax/src/validation.rs | 54 | ||||
-rw-r--r-- | crates/test_utils/src/lib.rs | 22 |
10 files changed, 212 insertions, 219 deletions
diff --git a/crates/ra_assists/src/introduce_variable.rs b/crates/ra_assists/src/introduce_variable.rs index 5eb708310..95c18d0e3 100644 --- a/crates/ra_assists/src/introduce_variable.rs +++ b/crates/ra_assists/src/introduce_variable.rs | |||
@@ -56,10 +56,7 @@ pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option | |||
56 | // but we do not want to duplicate possible | 56 | // but we do not want to duplicate possible |
57 | // extra newlines in the indent block | 57 | // extra newlines in the indent block |
58 | let text = indent.text(); | 58 | let text = indent.text(); |
59 | if text.starts_with("\r\n") { | 59 | if text.starts_with('\n') { |
60 | buf.push_str("\r\n"); | ||
61 | buf.push_str(text.trim_start_matches("\r\n")); | ||
62 | } else if text.starts_with('\n') { | ||
63 | buf.push_str("\n"); | 60 | buf.push_str("\n"); |
64 | buf.push_str(text.trim_start_matches('\n')); | 61 | buf.push_str(text.trim_start_matches('\n')); |
65 | } else { | 62 | } else { |
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index 2c69a6993..afeac0d8a 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml | |||
@@ -16,7 +16,7 @@ lsp-types = { version = "0.60.0", features = ["proposed"] } | |||
16 | rustc-hash = "1.0" | 16 | rustc-hash = "1.0" |
17 | parking_lot = "0.9.0" | 17 | parking_lot = "0.9.0" |
18 | 18 | ||
19 | ra_vfs = "0.2.0" | 19 | ra_vfs = "0.2.7" |
20 | thread_worker = { path = "../thread_worker" } | 20 | thread_worker = { path = "../thread_worker" } |
21 | ra_syntax = { path = "../ra_syntax" } | 21 | ra_syntax = { path = "../ra_syntax" } |
22 | ra_text_edit = { path = "../ra_text_edit" } | 22 | ra_text_edit = { path = "../ra_text_edit" } |
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index df8ea6e0d..0ad2ea10f 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs | |||
@@ -11,6 +11,7 @@ use ra_ide_api::{ | |||
11 | }; | 11 | }; |
12 | use ra_syntax::{SyntaxKind, TextRange, TextUnit}; | 12 | use ra_syntax::{SyntaxKind, TextRange, TextUnit}; |
13 | use ra_text_edit::{AtomTextEdit, TextEdit}; | 13 | use ra_text_edit::{AtomTextEdit, TextEdit}; |
14 | use ra_vfs::LineEndings; | ||
14 | 15 | ||
15 | use crate::{req, world::WorldSnapshot, Result}; | 16 | use crate::{req, world::WorldSnapshot, Result}; |
16 | 17 | ||
@@ -19,16 +20,14 @@ pub trait Conv { | |||
19 | fn conv(self) -> Self::Output; | 20 | fn conv(self) -> Self::Output; |
20 | } | 21 | } |
21 | 22 | ||
22 | pub trait ConvWith { | 23 | pub trait ConvWith<CTX> { |
23 | type Ctx; | ||
24 | type Output; | 24 | type Output; |
25 | fn conv_with(self, ctx: &Self::Ctx) -> Self::Output; | 25 | fn conv_with(self, ctx: CTX) -> Self::Output; |
26 | } | 26 | } |
27 | 27 | ||
28 | pub trait TryConvWith { | 28 | pub trait TryConvWith<CTX> { |
29 | type Ctx; | ||
30 | type Output; | 29 | type Output; |
31 | fn try_conv_with(self, ctx: &Self::Ctx) -> Result<Self::Output>; | 30 | fn try_conv_with(self, ctx: CTX) -> Result<Self::Output>; |
32 | } | 31 | } |
33 | 32 | ||
34 | impl Conv for SyntaxKind { | 33 | impl Conv for SyntaxKind { |
@@ -89,11 +88,10 @@ impl Conv for Severity { | |||
89 | } | 88 | } |
90 | } | 89 | } |
91 | 90 | ||
92 | impl ConvWith for CompletionItem { | 91 | impl ConvWith<(&LineIndex, LineEndings)> for CompletionItem { |
93 | type Ctx = LineIndex; | ||
94 | type Output = ::lsp_types::CompletionItem; | 92 | type Output = ::lsp_types::CompletionItem; |
95 | 93 | ||
96 | fn conv_with(self, ctx: &LineIndex) -> ::lsp_types::CompletionItem { | 94 | fn conv_with(self, ctx: (&LineIndex, LineEndings)) -> ::lsp_types::CompletionItem { |
97 | let mut additional_text_edits = Vec::new(); | 95 | let mut additional_text_edits = Vec::new(); |
98 | let mut text_edit = None; | 96 | let mut text_edit = None; |
99 | // LSP does not allow arbitrary edits in completion, so we have to do a | 97 | // LSP does not allow arbitrary edits in completion, so we have to do a |
@@ -138,8 +136,7 @@ impl ConvWith for CompletionItem { | |||
138 | } | 136 | } |
139 | } | 137 | } |
140 | 138 | ||
141 | impl ConvWith for Position { | 139 | impl ConvWith<&LineIndex> for Position { |
142 | type Ctx = LineIndex; | ||
143 | type Output = TextUnit; | 140 | type Output = TextUnit; |
144 | 141 | ||
145 | fn conv_with(self, line_index: &LineIndex) -> TextUnit { | 142 | fn conv_with(self, line_index: &LineIndex) -> TextUnit { |
@@ -148,8 +145,7 @@ impl ConvWith for Position { | |||
148 | } | 145 | } |
149 | } | 146 | } |
150 | 147 | ||
151 | impl ConvWith for TextUnit { | 148 | impl ConvWith<&LineIndex> for TextUnit { |
152 | type Ctx = LineIndex; | ||
153 | type Output = Position; | 149 | type Output = Position; |
154 | 150 | ||
155 | fn conv_with(self, line_index: &LineIndex) -> Position { | 151 | fn conv_with(self, line_index: &LineIndex) -> Position { |
@@ -158,8 +154,7 @@ impl ConvWith for TextUnit { | |||
158 | } | 154 | } |
159 | } | 155 | } |
160 | 156 | ||
161 | impl ConvWith for TextRange { | 157 | impl ConvWith<&LineIndex> for TextRange { |
162 | type Ctx = LineIndex; | ||
163 | type Output = Range; | 158 | type Output = Range; |
164 | 159 | ||
165 | fn conv_with(self, line_index: &LineIndex) -> Range { | 160 | fn conv_with(self, line_index: &LineIndex) -> Range { |
@@ -167,8 +162,7 @@ impl ConvWith for TextRange { | |||
167 | } | 162 | } |
168 | } | 163 | } |
169 | 164 | ||
170 | impl ConvWith for Range { | 165 | impl ConvWith<&LineIndex> for Range { |
171 | type Ctx = LineIndex; | ||
172 | type Output = TextRange; | 166 | type Output = TextRange; |
173 | 167 | ||
174 | fn conv_with(self, line_index: &LineIndex) -> TextRange { | 168 | fn conv_with(self, line_index: &LineIndex) -> TextRange { |
@@ -208,77 +202,73 @@ impl Conv for ra_ide_api::FunctionSignature { | |||
208 | } | 202 | } |
209 | } | 203 | } |
210 | 204 | ||
211 | impl ConvWith for TextEdit { | 205 | impl ConvWith<(&LineIndex, LineEndings)> for TextEdit { |
212 | type Ctx = LineIndex; | ||
213 | type Output = Vec<lsp_types::TextEdit>; | 206 | type Output = Vec<lsp_types::TextEdit>; |
214 | 207 | ||
215 | fn conv_with(self, line_index: &LineIndex) -> Vec<lsp_types::TextEdit> { | 208 | fn conv_with(self, ctx: (&LineIndex, LineEndings)) -> Vec<lsp_types::TextEdit> { |
216 | self.as_atoms().iter().map_conv_with(line_index).collect() | 209 | self.as_atoms().iter().map_conv_with(ctx).collect() |
217 | } | 210 | } |
218 | } | 211 | } |
219 | 212 | ||
220 | impl<'a> ConvWith for &'a AtomTextEdit { | 213 | impl ConvWith<(&LineIndex, LineEndings)> for &AtomTextEdit { |
221 | type Ctx = LineIndex; | ||
222 | type Output = lsp_types::TextEdit; | 214 | type Output = lsp_types::TextEdit; |
223 | 215 | ||
224 | fn conv_with(self, line_index: &LineIndex) -> lsp_types::TextEdit { | 216 | fn conv_with( |
225 | lsp_types::TextEdit { | 217 | self, |
226 | range: self.delete.conv_with(line_index), | 218 | (line_index, line_endings): (&LineIndex, LineEndings), |
227 | new_text: self.insert.clone(), | 219 | ) -> lsp_types::TextEdit { |
220 | let mut new_text = self.insert.clone(); | ||
221 | if line_endings == LineEndings::Dos { | ||
222 | new_text = new_text.replace('\n', "\r\n"); | ||
228 | } | 223 | } |
224 | lsp_types::TextEdit { range: self.delete.conv_with(line_index), new_text } | ||
229 | } | 225 | } |
230 | } | 226 | } |
231 | 227 | ||
232 | impl<T: ConvWith> ConvWith for Option<T> { | 228 | impl<T: ConvWith<CTX>, CTX> ConvWith<CTX> for Option<T> { |
233 | type Ctx = <T as ConvWith>::Ctx; | 229 | type Output = Option<T::Output>; |
234 | type Output = Option<<T as ConvWith>::Output>; | 230 | |
235 | fn conv_with(self, ctx: &Self::Ctx) -> Self::Output { | 231 | fn conv_with(self, ctx: CTX) -> Self::Output { |
236 | self.map(|x| ConvWith::conv_with(x, ctx)) | 232 | self.map(|x| ConvWith::conv_with(x, ctx)) |
237 | } | 233 | } |
238 | } | 234 | } |
239 | 235 | ||
240 | impl<'a> TryConvWith for &'a Url { | 236 | impl TryConvWith<&WorldSnapshot> for &Url { |
241 | type Ctx = WorldSnapshot; | ||
242 | type Output = FileId; | 237 | type Output = FileId; |
243 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<FileId> { | 238 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<FileId> { |
244 | world.uri_to_file_id(self) | 239 | world.uri_to_file_id(self) |
245 | } | 240 | } |
246 | } | 241 | } |
247 | 242 | ||
248 | impl TryConvWith for FileId { | 243 | impl TryConvWith<&WorldSnapshot> for FileId { |
249 | type Ctx = WorldSnapshot; | ||
250 | type Output = Url; | 244 | type Output = Url; |
251 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<Url> { | 245 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<Url> { |
252 | world.file_id_to_uri(self) | 246 | world.file_id_to_uri(self) |
253 | } | 247 | } |
254 | } | 248 | } |
255 | 249 | ||
256 | impl<'a> TryConvWith for &'a TextDocumentItem { | 250 | impl TryConvWith<&WorldSnapshot> for &TextDocumentItem { |
257 | type Ctx = WorldSnapshot; | ||
258 | type Output = FileId; | 251 | type Output = FileId; |
259 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<FileId> { | 252 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<FileId> { |
260 | self.uri.try_conv_with(world) | 253 | self.uri.try_conv_with(world) |
261 | } | 254 | } |
262 | } | 255 | } |
263 | 256 | ||
264 | impl<'a> TryConvWith for &'a VersionedTextDocumentIdentifier { | 257 | impl TryConvWith<&WorldSnapshot> for &VersionedTextDocumentIdentifier { |
265 | type Ctx = WorldSnapshot; | ||
266 | type Output = FileId; | 258 | type Output = FileId; |
267 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<FileId> { | 259 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<FileId> { |
268 | self.uri.try_conv_with(world) | 260 | self.uri.try_conv_with(world) |
269 | } | 261 | } |
270 | } | 262 | } |
271 | 263 | ||
272 | impl<'a> TryConvWith for &'a TextDocumentIdentifier { | 264 | impl TryConvWith<&WorldSnapshot> for &TextDocumentIdentifier { |
273 | type Ctx = WorldSnapshot; | ||
274 | type Output = FileId; | 265 | type Output = FileId; |
275 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<FileId> { | 266 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<FileId> { |
276 | world.uri_to_file_id(&self.uri) | 267 | world.uri_to_file_id(&self.uri) |
277 | } | 268 | } |
278 | } | 269 | } |
279 | 270 | ||
280 | impl<'a> TryConvWith for &'a TextDocumentPositionParams { | 271 | impl TryConvWith<&WorldSnapshot> for &TextDocumentPositionParams { |
281 | type Ctx = WorldSnapshot; | ||
282 | type Output = FilePosition; | 272 | type Output = FilePosition; |
283 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<FilePosition> { | 273 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<FilePosition> { |
284 | let file_id = self.text_document.try_conv_with(world)?; | 274 | let file_id = self.text_document.try_conv_with(world)?; |
@@ -288,8 +278,7 @@ impl<'a> TryConvWith for &'a TextDocumentPositionParams { | |||
288 | } | 278 | } |
289 | } | 279 | } |
290 | 280 | ||
291 | impl<'a> TryConvWith for (&'a TextDocumentIdentifier, Range) { | 281 | impl TryConvWith<&WorldSnapshot> for (&TextDocumentIdentifier, Range) { |
292 | type Ctx = WorldSnapshot; | ||
293 | type Output = FileRange; | 282 | type Output = FileRange; |
294 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<FileRange> { | 283 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<FileRange> { |
295 | let file_id = self.0.try_conv_with(world)?; | 284 | let file_id = self.0.try_conv_with(world)?; |
@@ -299,10 +288,9 @@ impl<'a> TryConvWith for (&'a TextDocumentIdentifier, Range) { | |||
299 | } | 288 | } |
300 | } | 289 | } |
301 | 290 | ||
302 | impl<T: TryConvWith> TryConvWith for Vec<T> { | 291 | impl<T: TryConvWith<CTX>, CTX: Copy> TryConvWith<CTX> for Vec<T> { |
303 | type Ctx = <T as TryConvWith>::Ctx; | 292 | type Output = Vec<<T as TryConvWith<CTX>>::Output>; |
304 | type Output = Vec<<T as TryConvWith>::Output>; | 293 | fn try_conv_with(self, ctx: CTX) -> Result<Self::Output> { |
305 | fn try_conv_with(self, ctx: &Self::Ctx) -> Result<Self::Output> { | ||
306 | let mut res = Vec::with_capacity(self.len()); | 294 | let mut res = Vec::with_capacity(self.len()); |
307 | for item in self { | 295 | for item in self { |
308 | res.push(item.try_conv_with(ctx)?); | 296 | res.push(item.try_conv_with(ctx)?); |
@@ -311,8 +299,7 @@ impl<T: TryConvWith> TryConvWith for Vec<T> { | |||
311 | } | 299 | } |
312 | } | 300 | } |
313 | 301 | ||
314 | impl TryConvWith for SourceChange { | 302 | impl TryConvWith<&WorldSnapshot> for SourceChange { |
315 | type Ctx = WorldSnapshot; | ||
316 | type Output = req::SourceChange; | 303 | type Output = req::SourceChange; |
317 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<req::SourceChange> { | 304 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<req::SourceChange> { |
318 | let cursor_position = match self.cursor_position { | 305 | let cursor_position = match self.cursor_position { |
@@ -351,8 +338,7 @@ impl TryConvWith for SourceChange { | |||
351 | } | 338 | } |
352 | } | 339 | } |
353 | 340 | ||
354 | impl TryConvWith for SourceFileEdit { | 341 | impl TryConvWith<&WorldSnapshot> for SourceFileEdit { |
355 | type Ctx = WorldSnapshot; | ||
356 | type Output = TextDocumentEdit; | 342 | type Output = TextDocumentEdit; |
357 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<TextDocumentEdit> { | 343 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<TextDocumentEdit> { |
358 | let text_document = VersionedTextDocumentIdentifier { | 344 | let text_document = VersionedTextDocumentIdentifier { |
@@ -360,13 +346,14 @@ impl TryConvWith for SourceFileEdit { | |||
360 | version: None, | 346 | version: None, |
361 | }; | 347 | }; |
362 | let line_index = world.analysis().file_line_index(self.file_id)?; | 348 | let line_index = world.analysis().file_line_index(self.file_id)?; |
363 | let edits = self.edit.as_atoms().iter().map_conv_with(&line_index).collect(); | 349 | let line_endings = world.file_line_endings(self.file_id); |
350 | let edits = | ||
351 | self.edit.as_atoms().iter().map_conv_with((&line_index, line_endings)).collect(); | ||
364 | Ok(TextDocumentEdit { text_document, edits }) | 352 | Ok(TextDocumentEdit { text_document, edits }) |
365 | } | 353 | } |
366 | } | 354 | } |
367 | 355 | ||
368 | impl TryConvWith for FileSystemEdit { | 356 | impl TryConvWith<&WorldSnapshot> for FileSystemEdit { |
369 | type Ctx = WorldSnapshot; | ||
370 | type Output = ResourceOp; | 357 | type Output = ResourceOp; |
371 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<ResourceOp> { | 358 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<ResourceOp> { |
372 | let res = match self { | 359 | let res = match self { |
@@ -384,8 +371,7 @@ impl TryConvWith for FileSystemEdit { | |||
384 | } | 371 | } |
385 | } | 372 | } |
386 | 373 | ||
387 | impl TryConvWith for &NavigationTarget { | 374 | impl TryConvWith<&WorldSnapshot> for &NavigationTarget { |
388 | type Ctx = WorldSnapshot; | ||
389 | type Output = Location; | 375 | type Output = Location; |
390 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<Location> { | 376 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<Location> { |
391 | let line_index = world.analysis().file_line_index(self.file_id())?; | 377 | let line_index = world.analysis().file_line_index(self.file_id())?; |
@@ -394,8 +380,7 @@ impl TryConvWith for &NavigationTarget { | |||
394 | } | 380 | } |
395 | } | 381 | } |
396 | 382 | ||
397 | impl TryConvWith for (FileId, RangeInfo<NavigationTarget>) { | 383 | impl TryConvWith<&WorldSnapshot> for (FileId, RangeInfo<NavigationTarget>) { |
398 | type Ctx = WorldSnapshot; | ||
399 | type Output = LocationLink; | 384 | type Output = LocationLink; |
400 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<LocationLink> { | 385 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<LocationLink> { |
401 | let (src_file_id, target) = self; | 386 | let (src_file_id, target) = self; |
@@ -422,8 +407,7 @@ impl TryConvWith for (FileId, RangeInfo<NavigationTarget>) { | |||
422 | } | 407 | } |
423 | } | 408 | } |
424 | 409 | ||
425 | impl TryConvWith for (FileId, RangeInfo<Vec<NavigationTarget>>) { | 410 | impl TryConvWith<&WorldSnapshot> for (FileId, RangeInfo<Vec<NavigationTarget>>) { |
426 | type Ctx = WorldSnapshot; | ||
427 | type Output = req::GotoDefinitionResponse; | 411 | type Output = req::GotoDefinitionResponse; |
428 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<req::GotoTypeDefinitionResponse> { | 412 | fn try_conv_with(self, world: &WorldSnapshot) -> Result<req::GotoTypeDefinitionResponse> { |
429 | let (file_id, RangeInfo { range, info: navs }) = self; | 413 | let (file_id, RangeInfo { range, info: navs }) = self; |
@@ -454,57 +438,55 @@ pub fn to_location( | |||
454 | Ok(loc) | 438 | Ok(loc) |
455 | } | 439 | } |
456 | 440 | ||
457 | pub trait MapConvWith<'a>: Sized + 'a { | 441 | pub trait MapConvWith<CTX>: Sized { |
458 | type Ctx; | ||
459 | type Output; | 442 | type Output; |
460 | 443 | ||
461 | fn map_conv_with(self, ctx: &'a Self::Ctx) -> ConvWithIter<'a, Self, Self::Ctx> { | 444 | fn map_conv_with(self, ctx: CTX) -> ConvWithIter<Self, CTX> { |
462 | ConvWithIter { iter: self, ctx } | 445 | ConvWithIter { iter: self, ctx } |
463 | } | 446 | } |
464 | } | 447 | } |
465 | 448 | ||
466 | impl<'a, I> MapConvWith<'a> for I | 449 | impl<CTX, I> MapConvWith<CTX> for I |
467 | where | 450 | where |
468 | I: Iterator + 'a, | 451 | I: Iterator, |
469 | I::Item: ConvWith, | 452 | I::Item: ConvWith<CTX>, |
470 | { | 453 | { |
471 | type Ctx = <I::Item as ConvWith>::Ctx; | 454 | type Output = <I::Item as ConvWith<CTX>>::Output; |
472 | type Output = <I::Item as ConvWith>::Output; | ||
473 | } | 455 | } |
474 | 456 | ||
475 | pub struct ConvWithIter<'a, I, Ctx: 'a> { | 457 | pub struct ConvWithIter<I, CTX> { |
476 | iter: I, | 458 | iter: I, |
477 | ctx: &'a Ctx, | 459 | ctx: CTX, |
478 | } | 460 | } |
479 | 461 | ||
480 | impl<'a, I, Ctx> Iterator for ConvWithIter<'a, I, Ctx> | 462 | impl<I, CTX> Iterator for ConvWithIter<I, CTX> |
481 | where | 463 | where |
482 | I: Iterator, | 464 | I: Iterator, |
483 | I::Item: ConvWith<Ctx = Ctx>, | 465 | I::Item: ConvWith<CTX>, |
466 | CTX: Copy, | ||
484 | { | 467 | { |
485 | type Item = <I::Item as ConvWith>::Output; | 468 | type Item = <I::Item as ConvWith<CTX>>::Output; |
486 | 469 | ||
487 | fn next(&mut self) -> Option<Self::Item> { | 470 | fn next(&mut self) -> Option<Self::Item> { |
488 | self.iter.next().map(|item| item.conv_with(self.ctx)) | 471 | self.iter.next().map(|item| item.conv_with(self.ctx)) |
489 | } | 472 | } |
490 | } | 473 | } |
491 | 474 | ||
492 | pub trait TryConvWithToVec<'a>: Sized + 'a { | 475 | pub trait TryConvWithToVec<CTX>: Sized { |
493 | type Ctx; | ||
494 | type Output; | 476 | type Output; |
495 | 477 | ||
496 | fn try_conv_with_to_vec(self, ctx: &'a Self::Ctx) -> Result<Vec<Self::Output>>; | 478 | fn try_conv_with_to_vec(self, ctx: CTX) -> Result<Vec<Self::Output>>; |
497 | } | 479 | } |
498 | 480 | ||
499 | impl<'a, I> TryConvWithToVec<'a> for I | 481 | impl<I, CTX> TryConvWithToVec<CTX> for I |
500 | where | 482 | where |
501 | I: Iterator + 'a, | 483 | I: Iterator, |
502 | I::Item: TryConvWith, | 484 | I::Item: TryConvWith<CTX>, |
485 | CTX: Copy, | ||
503 | { | 486 | { |
504 | type Ctx = <I::Item as TryConvWith>::Ctx; | 487 | type Output = <I::Item as TryConvWith<CTX>>::Output; |
505 | type Output = <I::Item as TryConvWith>::Output; | ||
506 | 488 | ||
507 | fn try_conv_with_to_vec(self, ctx: &'a Self::Ctx) -> Result<Vec<Self::Output>> { | 489 | fn try_conv_with_to_vec(self, ctx: CTX) -> Result<Vec<Self::Output>> { |
508 | self.map(|it| it.try_conv_with(ctx)).collect() | 490 | self.map(|it| it.try_conv_with(ctx)).collect() |
509 | } | 491 | } |
510 | } | 492 | } |
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index b465707f8..3a559e845 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -138,6 +138,7 @@ pub fn handle_on_type_formatting( | |||
138 | let _p = profile("handle_on_type_formatting"); | 138 | let _p = profile("handle_on_type_formatting"); |
139 | let mut position = params.text_document_position.try_conv_with(&world)?; | 139 | let mut position = params.text_document_position.try_conv_with(&world)?; |
140 | let line_index = world.analysis().file_line_index(position.file_id)?; | 140 | let line_index = world.analysis().file_line_index(position.file_id)?; |
141 | let line_endings = world.file_line_endings(position.file_id); | ||
141 | 142 | ||
142 | // in `ra_ide_api`, the `on_type` invariant is that | 143 | // in `ra_ide_api`, the `on_type` invariant is that |
143 | // `text.char_at(position) == typed_char`. | 144 | // `text.char_at(position) == typed_char`. |
@@ -156,7 +157,7 @@ pub fn handle_on_type_formatting( | |||
156 | // This should be a single-file edit | 157 | // This should be a single-file edit |
157 | let edit = edit.source_file_edits.pop().unwrap(); | 158 | let edit = edit.source_file_edits.pop().unwrap(); |
158 | 159 | ||
159 | let change: Vec<TextEdit> = edit.edit.conv_with(&line_index); | 160 | let change: Vec<TextEdit> = edit.edit.conv_with((&line_index, line_endings)); |
160 | Ok(Some(change)) | 161 | Ok(Some(change)) |
161 | } | 162 | } |
162 | 163 | ||
@@ -370,8 +371,9 @@ pub fn handle_completion( | |||
370 | Some(items) => items, | 371 | Some(items) => items, |
371 | }; | 372 | }; |
372 | let line_index = world.analysis().file_line_index(position.file_id)?; | 373 | let line_index = world.analysis().file_line_index(position.file_id)?; |
374 | let line_endings = world.file_line_endings(position.file_id); | ||
373 | let items: Vec<CompletionItem> = | 375 | let items: Vec<CompletionItem> = |
374 | items.into_iter().map(|item| item.conv_with(&line_index)).collect(); | 376 | items.into_iter().map(|item| item.conv_with((&line_index, line_endings))).collect(); |
375 | 377 | ||
376 | Ok(Some(items.into())) | 378 | Ok(Some(items.into())) |
377 | } | 379 | } |
diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index 9990ef62e..10f96812f 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs | |||
@@ -9,7 +9,7 @@ use parking_lot::RwLock; | |||
9 | use ra_ide_api::{ | 9 | use ra_ide_api::{ |
10 | Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId, | 10 | Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId, |
11 | }; | 11 | }; |
12 | use ra_vfs::{RootEntry, Vfs, VfsChange, VfsFile, VfsRoot}; | 12 | use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot}; |
13 | use ra_vfs_glob::{Glob, RustPackageFilterBuilder}; | 13 | use ra_vfs_glob::{Glob, RustPackageFilterBuilder}; |
14 | use relative_path::RelativePathBuf; | 14 | use relative_path::RelativePathBuf; |
15 | 15 | ||
@@ -210,6 +210,10 @@ impl WorldSnapshot { | |||
210 | Ok(url) | 210 | Ok(url) |
211 | } | 211 | } |
212 | 212 | ||
213 | pub fn file_line_endings(&self, id: FileId) -> LineEndings { | ||
214 | self.vfs.read().file_line_endings(VfsFile(id.0)) | ||
215 | } | ||
216 | |||
213 | pub fn path_to_uri(&self, root: SourceRootId, path: &RelativePathBuf) -> Result<Url> { | 217 | pub fn path_to_uri(&self, root: SourceRootId, path: &RelativePathBuf) -> Result<Url> { |
214 | let base = self.vfs.read().root2path(VfsRoot(root.0)); | 218 | let base = self.vfs.read().root2path(VfsRoot(root.0)); |
215 | let path = path.to_path(base); | 219 | let path = path.to_path(base); |
diff --git a/crates/ra_lsp_server/tests/heavy_tests/main.rs b/crates/ra_lsp_server/tests/heavy_tests/main.rs index de3bd5bc5..152681062 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/main.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/main.rs | |||
@@ -208,7 +208,7 @@ pub use std::collections::HashMap; | |||
208 | "range": { | 208 | "range": { |
209 | "end": { | 209 | "end": { |
210 | "character": 0, | 210 | "character": 0, |
211 | "line": 6 | 211 | "line": 7 |
212 | }, | 212 | }, |
213 | "start": { | 213 | "start": { |
214 | "character": 0, | 214 | "character": 0, |
@@ -414,3 +414,49 @@ fn main() {{}} | |||
414 | let elapsed = start.elapsed(); | 414 | let elapsed = start.elapsed(); |
415 | assert!(elapsed.as_millis() < 2000, "typing enter took {:?}", elapsed); | 415 | assert!(elapsed.as_millis() < 2000, "typing enter took {:?}", elapsed); |
416 | } | 416 | } |
417 | |||
418 | #[test] | ||
419 | fn preserves_dos_line_endings() { | ||
420 | let server = Project::with_fixture( | ||
421 | &" | ||
422 | //- Cargo.toml | ||
423 | [package] | ||
424 | name = \"foo\" | ||
425 | version = \"0.0.0\" | ||
426 | |||
427 | //- src/main.rs | ||
428 | /// Some Docs\r\nfn main() {} | ||
429 | ", | ||
430 | ) | ||
431 | .server(); | ||
432 | |||
433 | server.request::<OnEnter>( | ||
434 | TextDocumentPositionParams { | ||
435 | text_document: server.doc_id("src/main.rs"), | ||
436 | position: Position { line: 0, character: 8 }, | ||
437 | }, | ||
438 | json!({ | ||
439 | "cursorPosition": { | ||
440 | "position": { "line": 1, "character": 4 }, | ||
441 | "textDocument": { "uri": "file:///[..]src/main.rs" } | ||
442 | }, | ||
443 | "label": "on enter", | ||
444 | "workspaceEdit": { | ||
445 | "documentChanges": [ | ||
446 | { | ||
447 | "edits": [ | ||
448 | { | ||
449 | "newText": "\r\n/// ", | ||
450 | "range": { | ||
451 | "end": { "line": 0, "character": 8 }, | ||
452 | "start": { "line": 0, "character": 8 } | ||
453 | } | ||
454 | } | ||
455 | ], | ||
456 | "textDocument": { "uri": "file:///[..]src/main.rs", "version": null } | ||
457 | } | ||
458 | ] | ||
459 | } | ||
460 | }), | ||
461 | ); | ||
462 | } | ||
diff --git a/crates/ra_syntax/Cargo.toml b/crates/ra_syntax/Cargo.toml index 5f8585878..0ead277b2 100644 --- a/crates/ra_syntax/Cargo.toml +++ b/crates/ra_syntax/Cargo.toml | |||
@@ -10,7 +10,7 @@ repository = "https://github.com/rust-analyzer/rust-analyzer" | |||
10 | [dependencies] | 10 | [dependencies] |
11 | itertools = "0.8.0" | 11 | itertools = "0.8.0" |
12 | rowan = "0.6.1" | 12 | rowan = "0.6.1" |
13 | ra_rustc_lexer = { version = "0.1.0-pre.2" } | 13 | ra_rustc_lexer = { version = "0.1.0-pre.3", features = ["unicode-xid"] } |
14 | 14 | ||
15 | # ideally, `serde` should be enabled by `ra_lsp_server`, but we enable it here | 15 | # ideally, `serde` should be enabled by `ra_lsp_server`, but we enable it here |
16 | # to reduce number of compilations | 16 | # to reduce number of compilations |
diff --git a/crates/ra_syntax/src/parsing/lexer.rs b/crates/ra_syntax/src/parsing/lexer.rs index 06822ea91..bdb01d40b 100644 --- a/crates/ra_syntax/src/parsing/lexer.rs +++ b/crates/ra_syntax/src/parsing/lexer.rs | |||
@@ -12,16 +12,16 @@ pub struct Token { | |||
12 | pub len: TextUnit, | 12 | pub len: TextUnit, |
13 | } | 13 | } |
14 | 14 | ||
15 | fn match_literal_kind(kind: ra_rustc_lexer::LiteralKind) -> SyntaxKind { | 15 | fn match_literal_kind(kind: rustc_lexer::LiteralKind) -> SyntaxKind { |
16 | match kind { | 16 | match kind { |
17 | ra_rustc_lexer::LiteralKind::Int { .. } => INT_NUMBER, | 17 | rustc_lexer::LiteralKind::Int { .. } => INT_NUMBER, |
18 | ra_rustc_lexer::LiteralKind::Float { .. } => FLOAT_NUMBER, | 18 | rustc_lexer::LiteralKind::Float { .. } => FLOAT_NUMBER, |
19 | ra_rustc_lexer::LiteralKind::Char { .. } => CHAR, | 19 | rustc_lexer::LiteralKind::Char { .. } => CHAR, |
20 | ra_rustc_lexer::LiteralKind::Byte { .. } => BYTE, | 20 | rustc_lexer::LiteralKind::Byte { .. } => BYTE, |
21 | ra_rustc_lexer::LiteralKind::Str { .. } => STRING, | 21 | rustc_lexer::LiteralKind::Str { .. } => STRING, |
22 | ra_rustc_lexer::LiteralKind::ByteStr { .. } => BYTE_STRING, | 22 | rustc_lexer::LiteralKind::ByteStr { .. } => BYTE_STRING, |
23 | ra_rustc_lexer::LiteralKind::RawStr { .. } => RAW_STRING, | 23 | rustc_lexer::LiteralKind::RawStr { .. } => RAW_STRING, |
24 | ra_rustc_lexer::LiteralKind::RawByteStr { .. } => RAW_BYTE_STRING, | 24 | rustc_lexer::LiteralKind::RawByteStr { .. } => RAW_BYTE_STRING, |
25 | } | 25 | } |
26 | } | 26 | } |
27 | 27 | ||
@@ -32,32 +32,17 @@ pub fn tokenize(text: &str) -> Vec<Token> { | |||
32 | } | 32 | } |
33 | let mut text = text; | 33 | let mut text = text; |
34 | let mut acc = Vec::new(); | 34 | let mut acc = Vec::new(); |
35 | if let Some(len) = ra_rustc_lexer::strip_shebang(text) { | 35 | if let Some(len) = rustc_lexer::strip_shebang(text) { |
36 | acc.push(Token { kind: SHEBANG, len: TextUnit::from_usize(len) }); | 36 | acc.push(Token { kind: SHEBANG, len: TextUnit::from_usize(len) }); |
37 | text = &text[len..]; | 37 | text = &text[len..]; |
38 | } | 38 | } |
39 | while !text.is_empty() { | 39 | while !text.is_empty() { |
40 | let rustc_token = ra_rustc_lexer::first_token(text); | 40 | let rustc_token = rustc_lexer::first_token(text); |
41 | macro_rules! decompose { | ||
42 | ($t1:expr, $t2:expr) => {{ | ||
43 | acc.push(Token { kind: $t1, len: 1.into() }); | ||
44 | acc.push(Token { kind: $t2, len: 1.into() }); | ||
45 | text = &text[2..]; | ||
46 | continue; | ||
47 | }}; | ||
48 | ($t1:expr, $t2:expr, $t3:expr) => {{ | ||
49 | acc.push(Token { kind: $t1, len: 1.into() }); | ||
50 | acc.push(Token { kind: $t2, len: 1.into() }); | ||
51 | acc.push(Token { kind: $t3, len: 1.into() }); | ||
52 | text = &text[3..]; | ||
53 | continue; | ||
54 | }}; | ||
55 | } | ||
56 | let kind = match rustc_token.kind { | 41 | let kind = match rustc_token.kind { |
57 | ra_rustc_lexer::TokenKind::LineComment => COMMENT, | 42 | rustc_lexer::TokenKind::LineComment => COMMENT, |
58 | ra_rustc_lexer::TokenKind::BlockComment { .. } => COMMENT, | 43 | rustc_lexer::TokenKind::BlockComment { .. } => COMMENT, |
59 | ra_rustc_lexer::TokenKind::Whitespace => WHITESPACE, | 44 | rustc_lexer::TokenKind::Whitespace => WHITESPACE, |
60 | ra_rustc_lexer::TokenKind::Ident => { | 45 | rustc_lexer::TokenKind::Ident => { |
61 | let token_text = &text[..rustc_token.len]; | 46 | let token_text = &text[..rustc_token.len]; |
62 | if token_text == "_" { | 47 | if token_text == "_" { |
63 | UNDERSCORE | 48 | UNDERSCORE |
@@ -65,62 +50,37 @@ pub fn tokenize(text: &str) -> Vec<Token> { | |||
65 | SyntaxKind::from_keyword(&text[..rustc_token.len]).unwrap_or(IDENT) | 50 | SyntaxKind::from_keyword(&text[..rustc_token.len]).unwrap_or(IDENT) |
66 | } | 51 | } |
67 | } | 52 | } |
68 | ra_rustc_lexer::TokenKind::RawIdent => IDENT, | 53 | rustc_lexer::TokenKind::RawIdent => IDENT, |
69 | ra_rustc_lexer::TokenKind::Literal { kind, .. } => match_literal_kind(kind), | 54 | rustc_lexer::TokenKind::Literal { kind, .. } => match_literal_kind(kind), |
70 | ra_rustc_lexer::TokenKind::Lifetime { .. } => LIFETIME, | 55 | rustc_lexer::TokenKind::Lifetime { .. } => LIFETIME, |
71 | ra_rustc_lexer::TokenKind::Semi => SEMI, | 56 | rustc_lexer::TokenKind::Semi => SEMI, |
72 | ra_rustc_lexer::TokenKind::Comma => COMMA, | 57 | rustc_lexer::TokenKind::Comma => COMMA, |
73 | ra_rustc_lexer::TokenKind::DotDotDot => decompose!(DOT, DOT, DOT), | 58 | rustc_lexer::TokenKind::Dot => DOT, |
74 | ra_rustc_lexer::TokenKind::DotDotEq => decompose!(DOT, DOT, EQ), | 59 | rustc_lexer::TokenKind::OpenParen => L_PAREN, |
75 | ra_rustc_lexer::TokenKind::DotDot => decompose!(DOT, DOT), | 60 | rustc_lexer::TokenKind::CloseParen => R_PAREN, |
76 | ra_rustc_lexer::TokenKind::Dot => DOT, | 61 | rustc_lexer::TokenKind::OpenBrace => L_CURLY, |
77 | ra_rustc_lexer::TokenKind::OpenParen => L_PAREN, | 62 | rustc_lexer::TokenKind::CloseBrace => R_CURLY, |
78 | ra_rustc_lexer::TokenKind::CloseParen => R_PAREN, | 63 | rustc_lexer::TokenKind::OpenBracket => L_BRACK, |
79 | ra_rustc_lexer::TokenKind::OpenBrace => L_CURLY, | 64 | rustc_lexer::TokenKind::CloseBracket => R_BRACK, |
80 | ra_rustc_lexer::TokenKind::CloseBrace => R_CURLY, | 65 | rustc_lexer::TokenKind::At => AT, |
81 | ra_rustc_lexer::TokenKind::OpenBracket => L_BRACK, | 66 | rustc_lexer::TokenKind::Pound => POUND, |
82 | ra_rustc_lexer::TokenKind::CloseBracket => R_BRACK, | 67 | rustc_lexer::TokenKind::Tilde => TILDE, |
83 | ra_rustc_lexer::TokenKind::At => AT, | 68 | rustc_lexer::TokenKind::Question => QUESTION, |
84 | ra_rustc_lexer::TokenKind::Pound => POUND, | 69 | rustc_lexer::TokenKind::Colon => COLON, |
85 | ra_rustc_lexer::TokenKind::Tilde => TILDE, | 70 | rustc_lexer::TokenKind::Dollar => DOLLAR, |
86 | ra_rustc_lexer::TokenKind::Question => QUESTION, | 71 | rustc_lexer::TokenKind::Eq => EQ, |
87 | ra_rustc_lexer::TokenKind::ColonColon => decompose!(COLON, COLON), | 72 | rustc_lexer::TokenKind::Not => EXCL, |
88 | ra_rustc_lexer::TokenKind::Colon => COLON, | 73 | rustc_lexer::TokenKind::Lt => L_ANGLE, |
89 | ra_rustc_lexer::TokenKind::Dollar => DOLLAR, | 74 | rustc_lexer::TokenKind::Gt => R_ANGLE, |
90 | ra_rustc_lexer::TokenKind::EqEq => decompose!(EQ, EQ), | 75 | rustc_lexer::TokenKind::Minus => MINUS, |
91 | ra_rustc_lexer::TokenKind::Eq => EQ, | 76 | rustc_lexer::TokenKind::And => AMP, |
92 | ra_rustc_lexer::TokenKind::FatArrow => decompose!(EQ, R_ANGLE), | 77 | rustc_lexer::TokenKind::Or => PIPE, |
93 | ra_rustc_lexer::TokenKind::Ne => decompose!(EXCL, EQ), | 78 | rustc_lexer::TokenKind::Plus => PLUS, |
94 | ra_rustc_lexer::TokenKind::Not => EXCL, | 79 | rustc_lexer::TokenKind::Star => STAR, |
95 | ra_rustc_lexer::TokenKind::Le => decompose!(L_ANGLE, EQ), | 80 | rustc_lexer::TokenKind::Slash => SLASH, |
96 | ra_rustc_lexer::TokenKind::LArrow => decompose!(COLON, MINUS), | 81 | rustc_lexer::TokenKind::Caret => CARET, |
97 | ra_rustc_lexer::TokenKind::Lt => L_ANGLE, | 82 | rustc_lexer::TokenKind::Percent => PERCENT, |
98 | ra_rustc_lexer::TokenKind::ShlEq => decompose!(L_ANGLE, L_ANGLE, EQ), | 83 | rustc_lexer::TokenKind::Unknown => ERROR, |
99 | ra_rustc_lexer::TokenKind::Shl => decompose!(L_ANGLE, L_ANGLE), | ||
100 | ra_rustc_lexer::TokenKind::Ge => decompose!(R_ANGLE, EQ), | ||
101 | ra_rustc_lexer::TokenKind::Gt => R_ANGLE, | ||
102 | ra_rustc_lexer::TokenKind::ShrEq => decompose!(R_ANGLE, R_ANGLE, EQ), | ||
103 | ra_rustc_lexer::TokenKind::Shr => decompose!(R_ANGLE, R_ANGLE), | ||
104 | ra_rustc_lexer::TokenKind::RArrow => decompose!(MINUS, R_ANGLE), | ||
105 | ra_rustc_lexer::TokenKind::Minus => MINUS, | ||
106 | ra_rustc_lexer::TokenKind::MinusEq => decompose!(MINUS, EQ), | ||
107 | ra_rustc_lexer::TokenKind::And => AMP, | ||
108 | ra_rustc_lexer::TokenKind::AndAnd => decompose!(AMP, AMP), | ||
109 | ra_rustc_lexer::TokenKind::AndEq => decompose!(AMP, EQ), | ||
110 | ra_rustc_lexer::TokenKind::Or => PIPE, | ||
111 | ra_rustc_lexer::TokenKind::OrOr => decompose!(PIPE, PIPE), | ||
112 | ra_rustc_lexer::TokenKind::OrEq => decompose!(PIPE, EQ), | ||
113 | ra_rustc_lexer::TokenKind::PlusEq => decompose!(PLUS, EQ), | ||
114 | ra_rustc_lexer::TokenKind::Plus => PLUS, | ||
115 | ra_rustc_lexer::TokenKind::StarEq => decompose!(STAR, EQ), | ||
116 | ra_rustc_lexer::TokenKind::Star => STAR, | ||
117 | ra_rustc_lexer::TokenKind::SlashEq => decompose!(SLASH, EQ), | ||
118 | ra_rustc_lexer::TokenKind::Slash => SLASH, | ||
119 | ra_rustc_lexer::TokenKind::CaretEq => decompose!(CARET, EQ), | ||
120 | ra_rustc_lexer::TokenKind::Caret => CARET, | ||
121 | ra_rustc_lexer::TokenKind::PercentEq => decompose!(PERCENT, EQ), | ||
122 | ra_rustc_lexer::TokenKind::Percent => PERCENT, | ||
123 | ra_rustc_lexer::TokenKind::Unknown => ERROR, | ||
124 | }; | 84 | }; |
125 | let token = Token { kind, len: TextUnit::from_usize(rustc_token.len) }; | 85 | let token = Token { kind, len: TextUnit::from_usize(rustc_token.len) }; |
126 | acc.push(token); | 86 | acc.push(token); |
@@ -130,12 +90,12 @@ pub fn tokenize(text: &str) -> Vec<Token> { | |||
130 | } | 90 | } |
131 | 91 | ||
132 | pub fn classify_literal(text: &str) -> Option<Token> { | 92 | pub fn classify_literal(text: &str) -> Option<Token> { |
133 | let t = ra_rustc_lexer::first_token(text); | 93 | let t = rustc_lexer::first_token(text); |
134 | if t.len != text.len() { | 94 | if t.len != text.len() { |
135 | return None; | 95 | return None; |
136 | } | 96 | } |
137 | let kind = match t.kind { | 97 | let kind = match t.kind { |
138 | ra_rustc_lexer::TokenKind::Literal { kind, .. } => match_literal_kind(kind), | 98 | rustc_lexer::TokenKind::Literal { kind, .. } => match_literal_kind(kind), |
139 | _ => return None, | 99 | _ => return None, |
140 | }; | 100 | }; |
141 | Some(Token { kind, len: TextUnit::from_usize(t.len) }) | 101 | Some(Token { kind, len: TextUnit::from_usize(t.len) }) |
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs index 2bb3c0a03..a8c789e0c 100644 --- a/crates/ra_syntax/src/validation.rs +++ b/crates/ra_syntax/src/validation.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | mod block; | 1 | mod block; |
2 | 2 | ||
3 | use ra_rustc_lexer::unescape; | 3 | use rustc_lexer::unescape; |
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
6 | algo::visit::{visitor_ctx, VisitorCtx}, | 6 | algo::visit::{visitor_ctx, VisitorCtx}, |
@@ -32,64 +32,62 @@ pub enum EscapeError { | |||
32 | NonAsciiCharInByte, | 32 | NonAsciiCharInByte, |
33 | } | 33 | } |
34 | 34 | ||
35 | impl From<ra_rustc_lexer::unescape::EscapeError> for EscapeError { | 35 | impl From<rustc_lexer::unescape::EscapeError> for EscapeError { |
36 | fn from(err: ra_rustc_lexer::unescape::EscapeError) -> Self { | 36 | fn from(err: rustc_lexer::unescape::EscapeError) -> Self { |
37 | match err { | 37 | match err { |
38 | ra_rustc_lexer::unescape::EscapeError::ZeroChars => EscapeError::ZeroChars, | 38 | rustc_lexer::unescape::EscapeError::ZeroChars => EscapeError::ZeroChars, |
39 | ra_rustc_lexer::unescape::EscapeError::MoreThanOneChar => EscapeError::MoreThanOneChar, | 39 | rustc_lexer::unescape::EscapeError::MoreThanOneChar => EscapeError::MoreThanOneChar, |
40 | ra_rustc_lexer::unescape::EscapeError::LoneSlash => EscapeError::LoneSlash, | 40 | rustc_lexer::unescape::EscapeError::LoneSlash => EscapeError::LoneSlash, |
41 | ra_rustc_lexer::unescape::EscapeError::InvalidEscape => EscapeError::InvalidEscape, | 41 | rustc_lexer::unescape::EscapeError::InvalidEscape => EscapeError::InvalidEscape, |
42 | ra_rustc_lexer::unescape::EscapeError::BareCarriageReturn | 42 | rustc_lexer::unescape::EscapeError::BareCarriageReturn |
43 | | ra_rustc_lexer::unescape::EscapeError::BareCarriageReturnInRawString => { | 43 | | rustc_lexer::unescape::EscapeError::BareCarriageReturnInRawString => { |
44 | EscapeError::BareCarriageReturn | 44 | EscapeError::BareCarriageReturn |
45 | } | 45 | } |
46 | ra_rustc_lexer::unescape::EscapeError::EscapeOnlyChar => EscapeError::EscapeOnlyChar, | 46 | rustc_lexer::unescape::EscapeError::EscapeOnlyChar => EscapeError::EscapeOnlyChar, |
47 | ra_rustc_lexer::unescape::EscapeError::TooShortHexEscape => { | 47 | rustc_lexer::unescape::EscapeError::TooShortHexEscape => EscapeError::TooShortHexEscape, |
48 | EscapeError::TooShortHexEscape | 48 | rustc_lexer::unescape::EscapeError::InvalidCharInHexEscape => { |
49 | } | ||
50 | ra_rustc_lexer::unescape::EscapeError::InvalidCharInHexEscape => { | ||
51 | EscapeError::InvalidCharInHexEscape | 49 | EscapeError::InvalidCharInHexEscape |
52 | } | 50 | } |
53 | ra_rustc_lexer::unescape::EscapeError::OutOfRangeHexEscape => { | 51 | rustc_lexer::unescape::EscapeError::OutOfRangeHexEscape => { |
54 | EscapeError::OutOfRangeHexEscape | 52 | EscapeError::OutOfRangeHexEscape |
55 | } | 53 | } |
56 | ra_rustc_lexer::unescape::EscapeError::NoBraceInUnicodeEscape => { | 54 | rustc_lexer::unescape::EscapeError::NoBraceInUnicodeEscape => { |
57 | EscapeError::NoBraceInUnicodeEscape | 55 | EscapeError::NoBraceInUnicodeEscape |
58 | } | 56 | } |
59 | ra_rustc_lexer::unescape::EscapeError::InvalidCharInUnicodeEscape => { | 57 | rustc_lexer::unescape::EscapeError::InvalidCharInUnicodeEscape => { |
60 | EscapeError::InvalidCharInUnicodeEscape | 58 | EscapeError::InvalidCharInUnicodeEscape |
61 | } | 59 | } |
62 | ra_rustc_lexer::unescape::EscapeError::EmptyUnicodeEscape => { | 60 | rustc_lexer::unescape::EscapeError::EmptyUnicodeEscape => { |
63 | EscapeError::EmptyUnicodeEscape | 61 | EscapeError::EmptyUnicodeEscape |
64 | } | 62 | } |
65 | ra_rustc_lexer::unescape::EscapeError::UnclosedUnicodeEscape => { | 63 | rustc_lexer::unescape::EscapeError::UnclosedUnicodeEscape => { |
66 | EscapeError::UnclosedUnicodeEscape | 64 | EscapeError::UnclosedUnicodeEscape |
67 | } | 65 | } |
68 | ra_rustc_lexer::unescape::EscapeError::LeadingUnderscoreUnicodeEscape => { | 66 | rustc_lexer::unescape::EscapeError::LeadingUnderscoreUnicodeEscape => { |
69 | EscapeError::LeadingUnderscoreUnicodeEscape | 67 | EscapeError::LeadingUnderscoreUnicodeEscape |
70 | } | 68 | } |
71 | ra_rustc_lexer::unescape::EscapeError::OverlongUnicodeEscape => { | 69 | rustc_lexer::unescape::EscapeError::OverlongUnicodeEscape => { |
72 | EscapeError::OverlongUnicodeEscape | 70 | EscapeError::OverlongUnicodeEscape |
73 | } | 71 | } |
74 | ra_rustc_lexer::unescape::EscapeError::LoneSurrogateUnicodeEscape => { | 72 | rustc_lexer::unescape::EscapeError::LoneSurrogateUnicodeEscape => { |
75 | EscapeError::LoneSurrogateUnicodeEscape | 73 | EscapeError::LoneSurrogateUnicodeEscape |
76 | } | 74 | } |
77 | ra_rustc_lexer::unescape::EscapeError::OutOfRangeUnicodeEscape => { | 75 | rustc_lexer::unescape::EscapeError::OutOfRangeUnicodeEscape => { |
78 | EscapeError::OutOfRangeUnicodeEscape | 76 | EscapeError::OutOfRangeUnicodeEscape |
79 | } | 77 | } |
80 | ra_rustc_lexer::unescape::EscapeError::UnicodeEscapeInByte => { | 78 | rustc_lexer::unescape::EscapeError::UnicodeEscapeInByte => { |
81 | EscapeError::UnicodeEscapeInByte | 79 | EscapeError::UnicodeEscapeInByte |
82 | } | 80 | } |
83 | ra_rustc_lexer::unescape::EscapeError::NonAsciiCharInByte | 81 | rustc_lexer::unescape::EscapeError::NonAsciiCharInByte |
84 | | ra_rustc_lexer::unescape::EscapeError::NonAsciiCharInByteString => { | 82 | | rustc_lexer::unescape::EscapeError::NonAsciiCharInByteString => { |
85 | EscapeError::NonAsciiCharInByte | 83 | EscapeError::NonAsciiCharInByte |
86 | } | 84 | } |
87 | } | 85 | } |
88 | } | 86 | } |
89 | } | 87 | } |
90 | 88 | ||
91 | impl From<ra_rustc_lexer::unescape::EscapeError> for SyntaxErrorKind { | 89 | impl From<rustc_lexer::unescape::EscapeError> for SyntaxErrorKind { |
92 | fn from(err: ra_rustc_lexer::unescape::EscapeError) -> Self { | 90 | fn from(err: rustc_lexer::unescape::EscapeError) -> Self { |
93 | SyntaxErrorKind::EscapeError(err.into()) | 91 | SyntaxErrorKind::EscapeError(err.into()) |
94 | } | 92 | } |
95 | } | 93 | } |
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index ea99ac062..816d01f09 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs | |||
@@ -134,21 +134,25 @@ pub fn parse_fixture(fixture: &str) -> Vec<FixtureEntry> { | |||
134 | } | 134 | } |
135 | }; | 135 | }; |
136 | }; | 136 | }; |
137 | |||
137 | let margin = fixture | 138 | let margin = fixture |
138 | .lines() | 139 | .lines() |
139 | .filter(|it| it.trim_start().starts_with("//-")) | 140 | .filter(|it| it.trim_start().starts_with("//-")) |
140 | .map(|it| it.len() - it.trim_start().len()) | 141 | .map(|it| it.len() - it.trim_start().len()) |
141 | .next() | 142 | .next() |
142 | .expect("empty fixture"); | 143 | .expect("empty fixture"); |
143 | let lines = fixture.lines().filter_map(|line| { | 144 | |
144 | if line.len() >= margin { | 145 | let lines = fixture |
145 | assert!(line[..margin].trim().is_empty()); | 146 | .split('\n') // don't use `.lines` to not drop `\r\n` |
146 | Some(&line[margin..]) | 147 | .filter_map(|line| { |
147 | } else { | 148 | if line.len() >= margin { |
148 | assert!(line.trim().is_empty()); | 149 | assert!(line[..margin].trim().is_empty()); |
149 | None | 150 | Some(&line[margin..]) |
150 | } | 151 | } else { |
151 | }); | 152 | assert!(line.trim().is_empty()); |
153 | None | ||
154 | } | ||
155 | }); | ||
152 | 156 | ||
153 | for line in lines { | 157 | for line in lines { |
154 | if line.starts_with("//-") { | 158 | if line.starts_with("//-") { |