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') 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