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.rs67
1 files changed, 47 insertions, 20 deletions
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index f8f790e59..028b55902 100644
--- a/crates/ra_ide/src/syntax_highlighting.rs
+++ b/crates/ra_ide/src/syntax_highlighting.rs
@@ -121,7 +121,6 @@ pub(crate) fn highlight(
121 assert!(current_macro_call == Some(mc)); 121 assert!(current_macro_call == Some(mc));
122 current_macro_call = None; 122 current_macro_call = None;
123 format_string = None; 123 format_string = None;
124 continue;
125 } 124 }
126 _ => (), 125 _ => (),
127 } 126 }
@@ -150,7 +149,7 @@ pub(crate) fn highlight(
150 149
151 let range = element.text_range(); 150 let range = element.text_range();
152 151
153 let element_to_highlight = if current_macro_call.is_some() { 152 let element_to_highlight = if current_macro_call.is_some() && element.kind() != COMMENT {
154 // Inside a macro -- expand it first 153 // Inside a macro -- expand it first
155 let token = match element.clone().into_token() { 154 let token = match element.clone().into_token() {
156 Some(it) if it.parent().kind() == TOKEN_TREE => it, 155 Some(it) if it.parent().kind() == TOKEN_TREE => it,
@@ -237,7 +236,7 @@ pub(crate) fn highlight(
237 }); 236 });
238 } 237 }
239 } 238 }
240 stack.pop_and_inject(false); 239 stack.pop_and_inject(None);
241 } 240 }
242 } else if let Some(string) = 241 } else if let Some(string) =
243 element_to_highlight.as_token().cloned().and_then(ast::RawString::cast) 242 element_to_highlight.as_token().cloned().and_then(ast::RawString::cast)
@@ -325,16 +324,27 @@ impl HighlightedRangeStack {
325 cloned 324 cloned
326 } 325 }
327 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
328 /// Similar to `pop`, but can modify arbitrary prior ranges (where `pop`) 338 /// Similar to `pop`, but can modify arbitrary prior ranges (where `pop`)
329 /// can only modify the last range currently on the stack. 339 /// can only modify the last range currently on the stack.
330 /// 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
331 /// doctest injection below. 341 /// doctest injection below.
332 /// 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
333 /// intersected. 343 /// is overwritten with the argument.
334 /// 344 ///
335 /// 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
336 /// latter is computationally more expensive. 346 /// latter is computationally more expensive.
337 fn pop_and_inject(&mut self, delete: bool) { 347 fn pop_and_inject(&mut self, overwrite_parent: Option<Highlight>) {
338 let mut children = self.stack.pop().unwrap(); 348 let mut children = self.stack.pop().unwrap();
339 let prev = self.stack.last_mut().unwrap(); 349 let prev = self.stack.last_mut().unwrap();
340 children.sort_by_key(|range| range.range.start()); 350 children.sort_by_key(|range| range.range.start());
@@ -344,26 +354,45 @@ impl HighlightedRangeStack {
344 if let Some(idx) = 354 if let Some(idx) =
345 prev.iter().position(|parent| parent.range.contains_range(child.range)) 355 prev.iter().position(|parent| parent.range.contains_range(child.range))
346 { 356 {
357 if let Some(tag) = overwrite_parent {
358 prev[idx].highlight = tag;
359 }
360
347 let cloned = Self::intersect(&mut prev[idx], &child); 361 let cloned = Self::intersect(&mut prev[idx], &child);
348 let insert_idx = if delete || prev[idx].range.is_empty() { 362 let insert_idx = if prev[idx].range.is_empty() {
349 prev.remove(idx); 363 prev.remove(idx);
350 idx 364 idx
351 } else { 365 } else {
352 idx + 1 366 idx + 1
353 }; 367 };
354 prev.insert(insert_idx, child); 368 prev.insert(insert_idx, child);
355 if !delete && !cloned.range.is_empty() { 369 if !cloned.range.is_empty() {
356 prev.insert(insert_idx + 1, cloned); 370 prev.insert(insert_idx + 1, cloned);
357 } 371 }
358 } else if let Some(_idx) =
359 prev.iter().position(|parent| parent.range.contains(child.range.start()))
360 {
361 unreachable!("child range should be completely contained in parent range");
362 } else { 372 } else {
363 let idx = prev 373 let maybe_idx =
364 .binary_search_by_key(&child.range.start(), |range| range.range.start()) 374 prev.iter().position(|parent| parent.range.contains(child.range.start()));
365 .unwrap_or_else(|x| x); 375 match (overwrite_parent, maybe_idx) {
366 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 }
367 } 396 }
368 } 397 }
369 } 398 }
@@ -517,11 +546,9 @@ fn highlight_element(
517 let ty = sema.type_of_expr(&expr)?; 546 let ty = sema.type_of_expr(&expr)?;
518 if !ty.is_raw_ptr() { 547 if !ty.is_raw_ptr() {
519 return None; 548 return None;
549 } else {
550 HighlightTag::Operator | HighlightModifier::Unsafe
520 } 551 }
521
522 let mut h = Highlight::new(HighlightTag::Operator);
523 h |= HighlightModifier::Unsafe;
524 h
525 } 552 }
526 T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => { 553 T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => {
527 Highlight::new(HighlightTag::Macro) 554 Highlight::new(HighlightTag::Macro)