diff options
Diffstat (limited to 'crates/ra_ide/src/syntax_highlighting.rs')
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting.rs | 55 |
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 | ||