From 8f6f864547bad3d2bb34ea0cf5a32e8adee58c4e Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Tue, 25 Feb 2020 08:38:50 -0500 Subject: Semantic Ranges --- crates/ra_ide/src/lib.rs | 7 +++++ crates/ra_ide/src/syntax_highlighting.rs | 49 ++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 3 deletions(-) (limited to 'crates/ra_ide/src') diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 82e10bc7e..c02bb08a0 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs @@ -430,6 +430,13 @@ impl Analysis { self.with_db(|db| syntax_highlighting::highlight(db, file_id)) } + /// Computes syntax highlighting for the given file range. + pub fn highlight_range(&self, frange: FileRange) -> Cancelable> { + self.with_db(|db| { + syntax_highlighting::highlight_range(db, frange.file_id, Some(frange.range)) + }) + } + /// Computes syntax highlighting for the given file. pub fn highlight_as_html(&self, file_id: FileId, rainbow: bool) -> Cancelable { self.with_db(|db| syntax_highlighting::highlight_as_html(db, file_id, rainbow)) diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 812229b4e..22c84561f 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs @@ -5,8 +5,8 @@ use ra_db::SourceDatabase; use ra_ide_db::{defs::NameDefinition, RootDatabase}; use ra_prof::profile; use ra_syntax::{ - ast, AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxKind::*, SyntaxToken, TextRange, - WalkEvent, T, + ast, AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxKind::*, SyntaxToken, + TextRange, WalkEvent, T, }; use rustc_hash::FxHashMap; @@ -69,6 +69,16 @@ fn is_control_keyword(kind: SyntaxKind) -> bool { pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec { let _p = profile("highlight"); + highlight_range(db, file_id, None) +} + +pub(crate) fn highlight_range( + db: &RootDatabase, + file_id: FileId, + range: Option, +) -> Vec { + let _p = profile("highlight_range"); + let parse = db.parse(file_id); let root = parse.tree().syntax().clone(); @@ -79,6 +89,15 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec match root.covering_element(range) { + NodeOrToken::Node(node) => node, + NodeOrToken::Token(token) => token.parent(), + }, + None => root, + }; + for event in root.preorder_with_tokens() { match event { WalkEvent::Enter(node) => match node.kind() { @@ -374,7 +393,10 @@ mod tests { use test_utils::{assert_eq_text, project_dir, read_text}; - use crate::mock_analysis::{single_file, MockAnalysis}; + use crate::{ + mock_analysis::{single_file, MockAnalysis}, + FileRange, TextRange, + }; #[test] fn test_highlighting() { @@ -475,4 +497,25 @@ fn bar() { let _ = host.analysis().highlight(file_id).unwrap(); // eprintln!("elapsed: {:?}", t.elapsed()); } + + #[test] + fn test_ranges() { + let (analysis, file_id) = single_file( + r#" + #[derive(Clone, Debug)] + struct Foo { + pub x: i32, + pub y: i32, + }"#, + ); + + let highlights = &analysis + .highlight_range(FileRange { + file_id, + range: TextRange::offset_len(82.into(), 1.into()), // "x" + }) + .unwrap(); + + assert_eq!(highlights[0].tag, "field"); + } } -- cgit v1.2.3 From fa355d6339d7b5ccfd4b1a96f035a4366e8152fe Mon Sep 17 00:00:00 2001 From: kjeremy Date: Tue, 25 Feb 2020 14:44:47 -0500 Subject: Rename back to highlight and check event's again highlight range --- crates/ra_ide/src/lib.rs | 8 ++- crates/ra_ide/src/syntax_highlighting.rs | 86 +++++++++++++++++++------------- 2 files changed, 54 insertions(+), 40 deletions(-) (limited to 'crates/ra_ide/src') diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index c02bb08a0..d22870669 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs @@ -425,16 +425,14 @@ impl Analysis { self.with_db(|db| runnables::runnables(db, file_id)) } - /// Computes syntax highlighting for the given file. + /// Computes syntax highlighting for the given file pub fn highlight(&self, file_id: FileId) -> Cancelable> { - self.with_db(|db| syntax_highlighting::highlight(db, file_id)) + self.with_db(|db| syntax_highlighting::highlight(db, file_id, None)) } /// Computes syntax highlighting for the given file range. pub fn highlight_range(&self, frange: FileRange) -> Cancelable> { - self.with_db(|db| { - syntax_highlighting::highlight_range(db, frange.file_id, Some(frange.range)) - }) + self.with_db(|db| syntax_highlighting::highlight(db, frange.file_id, Some(frange.range))) } /// Computes syntax highlighting for the given file. diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 22c84561f..9bc3ad448 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs @@ -67,17 +67,12 @@ fn is_control_keyword(kind: SyntaxKind) -> bool { } } -pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec { - let _p = profile("highlight"); - highlight_range(db, file_id, None) -} - -pub(crate) fn highlight_range( +pub(crate) fn highlight( db: &RootDatabase, file_id: FileId, range: Option, ) -> Vec { - let _p = profile("highlight_range"); + let _p = profile("highlight"); let parse = db.parse(file_id); let root = parse.tree().syntax().clone(); @@ -89,31 +84,56 @@ pub(crate) fn highlight_range( let mut in_macro_call = None; - // Determine the root based on the range - let root = match range { - Some(range) => match root.covering_element(range) { + // Determine the root based on the given range. + let (root, highlight_range) = if let Some(range) = range { + let root = match root.covering_element(range) { NodeOrToken::Node(node) => node, NodeOrToken::Token(token) => token.parent(), - }, - None => root, + }; + (root, range) + } else { + (root.clone(), root.text_range()) }; for event in root.preorder_with_tokens() { match event { - WalkEvent::Enter(node) => match node.kind() { - MACRO_CALL => { - in_macro_call = Some(node.clone()); - if let Some(range) = highlight_macro(InFile::new(file_id.into(), node)) { - res.push(HighlightedRange { range, tag: tags::MACRO, binding_hash: None }); - } + WalkEvent::Enter(node) => { + if node.text_range().intersection(&highlight_range).is_none() { + continue; } - _ if in_macro_call.is_some() => { - if let Some(token) = node.as_token() { - if let Some((tag, binding_hash)) = highlight_token_tree( + + match node.kind() { + MACRO_CALL => { + in_macro_call = Some(node.clone()); + if let Some(range) = highlight_macro(InFile::new(file_id.into(), node)) { + res.push(HighlightedRange { + range, + tag: tags::MACRO, + binding_hash: None, + }); + } + } + _ if in_macro_call.is_some() => { + if let Some(token) = node.as_token() { + if let Some((tag, binding_hash)) = highlight_token_tree( + &mut sb, + &analyzer, + &mut bindings_shadow_count, + InFile::new(file_id.into(), token.clone()), + ) { + res.push(HighlightedRange { + range: node.text_range(), + tag, + binding_hash, + }); + } + } + } + _ => { + if let Some((tag, binding_hash)) = highlight_node( &mut sb, - &analyzer, &mut bindings_shadow_count, - InFile::new(file_id.into(), token.clone()), + InFile::new(file_id.into(), node.clone()), ) { res.push(HighlightedRange { range: node.text_range(), @@ -123,17 +143,12 @@ pub(crate) fn highlight_range( } } } - _ => { - if let Some((tag, binding_hash)) = highlight_node( - &mut sb, - &mut bindings_shadow_count, - InFile::new(file_id.into(), node.clone()), - ) { - res.push(HighlightedRange { range: node.text_range(), tag, binding_hash }); - } - } - }, + } WalkEvent::Leave(node) => { + if node.text_range().intersection(&highlight_range).is_none() { + continue; + } + if let Some(m) = in_macro_call.as_ref() { if *m == node { in_macro_call = None; @@ -284,7 +299,7 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo ) } - let mut ranges = highlight(db, file_id); + let mut ranges = highlight(db, file_id, None); ranges.sort_by_key(|it| it.range.start()); // quick non-optimal heuristic to intersect token ranges and highlighted ranges let mut frontier = 0; @@ -509,10 +524,11 @@ fn bar() { }"#, ); + // The "x" let highlights = &analysis .highlight_range(FileRange { file_id, - range: TextRange::offset_len(82.into(), 1.into()), // "x" + range: TextRange::offset_len(82.into(), 1.into()), }) .unwrap(); -- cgit v1.2.3