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.rs55
1 files changed, 38 insertions, 17 deletions
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index 8e714a999..3dffddce5 100644
--- a/crates/ra_ide/src/syntax_highlighting.rs
+++ b/crates/ra_ide/src/syntax_highlighting.rs
@@ -45,7 +45,6 @@ pub(crate) fn highlight(
45 file_id: FileId, 45 file_id: FileId,
46 range_to_highlight: Option<TextRange>, 46 range_to_highlight: Option<TextRange>,
47 syntactic_name_ref_highlighting: bool, 47 syntactic_name_ref_highlighting: bool,
48 should_highlight_punctuation: bool,
49) -> Vec<HighlightedRange> { 48) -> Vec<HighlightedRange> {
50 let _p = profile("highlight"); 49 let _p = profile("highlight");
51 let sema = Semantics::new(db); 50 let sema = Semantics::new(db);
@@ -108,7 +107,6 @@ pub(crate) fn highlight(
108 &mut bindings_shadow_count, 107 &mut bindings_shadow_count,
109 syntactic_name_ref_highlighting, 108 syntactic_name_ref_highlighting,
110 name.syntax().clone().into(), 109 name.syntax().clone().into(),
111 should_highlight_punctuation,
112 ) { 110 ) {
113 stack.add(HighlightedRange { 111 stack.add(HighlightedRange {
114 range: name.syntax().text_range(), 112 range: name.syntax().text_range(),
@@ -208,7 +206,6 @@ pub(crate) fn highlight(
208 &mut bindings_shadow_count, 206 &mut bindings_shadow_count,
209 syntactic_name_ref_highlighting, 207 syntactic_name_ref_highlighting,
210 element_to_highlight.clone(), 208 element_to_highlight.clone(),
211 true,
212 ) { 209 ) {
213 stack.add(HighlightedRange { range, highlight, binding_hash }); 210 stack.add(HighlightedRange { range, highlight, binding_hash });
214 if let Some(string) = 211 if let Some(string) =
@@ -239,7 +236,7 @@ pub(crate) fn highlight(
239 }); 236 });
240 } 237 }
241 } 238 }
242 stack.pop_and_inject(false); 239 stack.pop_and_inject(None);
243 } 240 }
244 } else if let Some(string) = 241 } else if let Some(string) =
245 element_to_highlight.as_token().cloned().and_then(ast::RawString::cast) 242 element_to_highlight.as_token().cloned().and_then(ast::RawString::cast)
@@ -327,6 +324,17 @@ impl HighlightedRangeStack {
327 cloned 324 cloned
328 } 325 }
329 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
330 /// Similar to `pop`, but can modify arbitrary prior ranges (where `pop`) 338 /// Similar to `pop`, but can modify arbitrary prior ranges (where `pop`)
331 /// can only modify the last range currently on the stack. 339 /// can only modify the last range currently on the stack.
332 /// 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
@@ -336,7 +344,7 @@ impl HighlightedRangeStack {
336 /// 344 ///
337 /// 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
338 /// latter is computationally more expensive. 346 /// latter is computationally more expensive.
339 fn pop_and_inject(&mut self, inject: bool) { 347 fn pop_and_inject(&mut self, overwrite_parent: Option<Highlight>) {
340 let mut children = self.stack.pop().unwrap(); 348 let mut children = self.stack.pop().unwrap();
341 let prev = self.stack.last_mut().unwrap(); 349 let prev = self.stack.last_mut().unwrap();
342 children.sort_by_key(|range| range.range.start()); 350 children.sort_by_key(|range| range.range.start());
@@ -346,26 +354,41 @@ impl HighlightedRangeStack {
346 if let Some(idx) = 354 if let Some(idx) =
347 prev.iter().position(|parent| parent.range.contains_range(child.range)) 355 prev.iter().position(|parent| parent.range.contains_range(child.range))
348 { 356 {
357 if let Some(tag) = overwrite_parent {
358 prev[idx].highlight = tag;
359 }
360
349 let cloned = Self::intersect(&mut prev[idx], &child); 361 let cloned = Self::intersect(&mut prev[idx], &child);
350 let insert_idx = if inject || prev[idx].range.is_empty() { 362 let insert_idx = if prev[idx].range.is_empty() {
351 prev.remove(idx); 363 prev.remove(idx);
352 idx 364 idx
353 } else { 365 } else {
354 idx + 1 366 idx + 1
355 }; 367 };
356 prev.insert(insert_idx, child); 368 prev.insert(insert_idx, child);
357 if !inject && !cloned.range.is_empty() { 369 if !cloned.range.is_empty() {
358 prev.insert(insert_idx + 1, cloned); 370 prev.insert(insert_idx + 1, cloned);
359 } 371 }
360 } else if let Some(_idx) =
361 prev.iter().position(|parent| parent.range.contains(child.range.start()))
362 {
363 unreachable!("child range should be completely contained in parent range");
364 } else { 372 } else {
365 let idx = prev 373 let maybe_idx =
366 .binary_search_by_key(&child.range.start(), |range| range.range.start()) 374 prev.iter().position(|parent| parent.range.contains(child.range.start()));
367 .unwrap_or_else(|x| x); 375 if let (Some(_), Some(idx)) = (overwrite_parent, maybe_idx) {
368 prev.insert(idx, child); 376 Self::intersect_partial(&mut prev[idx], &child);
377 let insert_idx = if prev[idx].range.is_empty() {
378 prev.remove(idx);
379 idx
380 } else {
381 idx + 1
382 };
383 prev.insert(insert_idx, child);
384 } else if let None = maybe_idx {
385 let idx = prev
386 .binary_search_by_key(&child.range.start(), |range| range.range.start())
387 .unwrap_or_else(|x| x);
388 prev.insert(idx, child);
389 } else {
390 unreachable!("child range should be completely contained in parent range");
391 }
369 } 392 }
370 } 393 }
371 } 394 }
@@ -433,7 +456,6 @@ fn highlight_element(
433 bindings_shadow_count: &mut FxHashMap<Name, u32>, 456 bindings_shadow_count: &mut FxHashMap<Name, u32>,
434 syntactic_name_ref_highlighting: bool, 457 syntactic_name_ref_highlighting: bool,
435 element: SyntaxElement, 458 element: SyntaxElement,
436 should_highlight_punctuation: bool,
437) -> Option<(Highlight, Option<u64>)> { 459) -> Option<(Highlight, Option<u64>)> {
438 let db = sema.db; 460 let db = sema.db;
439 let mut binding_hash = None; 461 let mut binding_hash = None;
@@ -550,7 +572,6 @@ fn highlight_element(
550 } 572 }
551 } 573 }
552 574
553 p if should_highlight_punctuation && p.is_punct() => HighlightTag::Punctuation.into(),
554 _ => return None, 575 _ => return None,
555 }; 576 };
556 577