aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/syntax_highlighting.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/syntax_highlighting.rs')
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs64
1 files changed, 46 insertions, 18 deletions
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index 448645bdc..028b55902 100644
--- a/crates/ra_ide/src/syntax_highlighting.rs
+++ b/crates/ra_ide/src/syntax_highlighting.rs
@@ -236,7 +236,7 @@ pub(crate) fn highlight(
236 }); 236 });
237 } 237 }
238 } 238 }
239 stack.pop_and_inject(false); 239 stack.pop_and_inject(None);
240 } 240 }
241 } else if let Some(string) = 241 } else if let Some(string) =
242 element_to_highlight.as_token().cloned().and_then(ast::RawString::cast) 242 element_to_highlight.as_token().cloned().and_then(ast::RawString::cast)
@@ -324,16 +324,27 @@ impl HighlightedRangeStack {
324 cloned 324 cloned
325 } 325 }
326 326
327 /// Remove the `HighlightRange` of `parent` that's currently covered by `child`.
328 fn intersect_partial(parent: &mut HighlightedRange, child: &HighlightedRange) {
329 assert!(
330 parent.range.start() <= child.range.start()
331 && parent.range.end() >= child.range.start()
332 && child.range.end() > parent.range.end()
333 );
334
335 parent.range = TextRange::new(parent.range.start(), child.range.start());
336 }
337
327 /// Similar to `pop`, but can modify arbitrary prior ranges (where `pop`) 338 /// Similar to `pop`, but can modify arbitrary prior ranges (where `pop`)
328 /// can only modify the last range currently on the stack. 339 /// can only modify the last range currently on the stack.
329 /// Can be used to do injections that span multiple ranges, like the 340 /// Can be used to do injections that span multiple ranges, like the
330 /// doctest injection below. 341 /// doctest injection below.
331 /// If `delete` is set to true, the parent range is deleted instead of 342 /// If `overwrite_parent` is non-optional, the highlighting of the parent range
332 /// intersected. 343 /// is overwritten with the argument.
333 /// 344 ///
334 /// Note that `pop` can be simulated by `pop_and_inject(false)` but the 345 /// Note that `pop` can be simulated by `pop_and_inject(false)` but the
335 /// latter is computationally more expensive. 346 /// latter is computationally more expensive.
336 fn pop_and_inject(&mut self, delete: bool) { 347 fn pop_and_inject(&mut self, overwrite_parent: Option<Highlight>) {
337 let mut children = self.stack.pop().unwrap(); 348 let mut children = self.stack.pop().unwrap();
338 let prev = self.stack.last_mut().unwrap(); 349 let prev = self.stack.last_mut().unwrap();
339 children.sort_by_key(|range| range.range.start()); 350 children.sort_by_key(|range| range.range.start());
@@ -343,26 +354,45 @@ impl HighlightedRangeStack {
343 if let Some(idx) = 354 if let Some(idx) =
344 prev.iter().position(|parent| parent.range.contains_range(child.range)) 355 prev.iter().position(|parent| parent.range.contains_range(child.range))
345 { 356 {
357 if let Some(tag) = overwrite_parent {
358 prev[idx].highlight = tag;
359 }
360
346 let cloned = Self::intersect(&mut prev[idx], &child); 361 let cloned = Self::intersect(&mut prev[idx], &child);
347 let insert_idx = if delete || prev[idx].range.is_empty() { 362 let insert_idx = if prev[idx].range.is_empty() {
348 prev.remove(idx); 363 prev.remove(idx);
349 idx 364 idx
350 } else { 365 } else {
351 idx + 1 366 idx + 1
352 }; 367 };
353 prev.insert(insert_idx, child); 368 prev.insert(insert_idx, child);
354 if !delete && !cloned.range.is_empty() { 369 if !cloned.range.is_empty() {
355 prev.insert(insert_idx + 1, cloned); 370 prev.insert(insert_idx + 1, cloned);
356 } 371 }
357 } else if let Some(_idx) =
358 prev.iter().position(|parent| parent.range.contains(child.range.start()))
359 {
360 unreachable!("child range should be completely contained in parent range");
361 } else { 372 } else {
362 let idx = prev 373 let maybe_idx =
363 .binary_search_by_key(&child.range.start(), |range| range.range.start()) 374 prev.iter().position(|parent| parent.range.contains(child.range.start()));
364 .unwrap_or_else(|x| x); 375 match (overwrite_parent, maybe_idx) {
365 prev.insert(idx, child); 376 (Some(_), Some(idx)) => {
377 Self::intersect_partial(&mut prev[idx], &child);
378 let insert_idx = if prev[idx].range.is_empty() {
379 prev.remove(idx);
380 idx
381 } else {
382 idx + 1
383 };
384 prev.insert(insert_idx, child);
385 }
386 (_, None) => {
387 let idx = prev
388 .binary_search_by_key(&child.range.start(), |range| range.range.start())
389 .unwrap_or_else(|x| x);
390 prev.insert(idx, child);
391 }
392 _ => {
393 unreachable!("child range should be completely contained in parent range");
394 }
395 }
366 } 396 }
367 } 397 }
368 } 398 }
@@ -516,11 +546,9 @@ fn highlight_element(
516 let ty = sema.type_of_expr(&expr)?; 546 let ty = sema.type_of_expr(&expr)?;
517 if !ty.is_raw_ptr() { 547 if !ty.is_raw_ptr() {
518 return None; 548 return None;
549 } else {
550 HighlightTag::Operator | HighlightModifier::Unsafe
519 } 551 }
520
521 let mut h = Highlight::new(HighlightTag::Operator);
522 h |= HighlightModifier::Unsafe;
523 h
524 } 552 }
525 T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => { 553 T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => {
526 Highlight::new(HighlightTag::Macro) 554 Highlight::new(HighlightTag::Macro)