Skip to content

Commit 8f6f864

Browse files
committed
Semantic Ranges
1 parent d3040c0 commit 8f6f864

File tree

6 files changed

+92
-16
lines changed

6 files changed

+92
-16
lines changed

crates/ra_ide/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,13 @@ impl Analysis {
430430
self.with_db(|db| syntax_highlighting::highlight(db, file_id))
431431
}
432432

433+
/// Computes syntax highlighting for the given file range.
434+
pub fn highlight_range(&self, frange: FileRange) -> Cancelable<Vec<HighlightedRange>> {
435+
self.with_db(|db| {
436+
syntax_highlighting::highlight_range(db, frange.file_id, Some(frange.range))
437+
})
438+
}
439+
433440
/// Computes syntax highlighting for the given file.
434441
pub fn highlight_as_html(&self, file_id: FileId, rainbow: bool) -> Cancelable<String> {
435442
self.with_db(|db| syntax_highlighting::highlight_as_html(db, file_id, rainbow))

crates/ra_ide/src/syntax_highlighting.rs

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use ra_db::SourceDatabase;
55
use ra_ide_db::{defs::NameDefinition, RootDatabase};
66
use ra_prof::profile;
77
use ra_syntax::{
8-
ast, AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxKind::*, SyntaxToken, TextRange,
9-
WalkEvent, T,
8+
ast, AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxKind::*, SyntaxToken,
9+
TextRange, WalkEvent, T,
1010
};
1111
use rustc_hash::FxHashMap;
1212

@@ -69,6 +69,16 @@ fn is_control_keyword(kind: SyntaxKind) -> bool {
6969

7070
pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRange> {
7171
let _p = profile("highlight");
72+
highlight_range(db, file_id, None)
73+
}
74+
75+
pub(crate) fn highlight_range(
76+
db: &RootDatabase,
77+
file_id: FileId,
78+
range: Option<TextRange>,
79+
) -> Vec<HighlightedRange> {
80+
let _p = profile("highlight_range");
81+
7282
let parse = db.parse(file_id);
7383
let root = parse.tree().syntax().clone();
7484

@@ -79,6 +89,15 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
7989

8090
let mut in_macro_call = None;
8191

92+
// Determine the root based on the range
93+
let root = match range {
94+
Some(range) => match root.covering_element(range) {
95+
NodeOrToken::Node(node) => node,
96+
NodeOrToken::Token(token) => token.parent(),
97+
},
98+
None => root,
99+
};
100+
82101
for event in root.preorder_with_tokens() {
83102
match event {
84103
WalkEvent::Enter(node) => match node.kind() {
@@ -374,7 +393,10 @@ mod tests {
374393

375394
use test_utils::{assert_eq_text, project_dir, read_text};
376395

377-
use crate::mock_analysis::{single_file, MockAnalysis};
396+
use crate::{
397+
mock_analysis::{single_file, MockAnalysis},
398+
FileRange, TextRange,
399+
};
378400

379401
#[test]
380402
fn test_highlighting() {
@@ -475,4 +497,25 @@ fn bar() {
475497
let _ = host.analysis().highlight(file_id).unwrap();
476498
// eprintln!("elapsed: {:?}", t.elapsed());
477499
}
500+
501+
#[test]
502+
fn test_ranges() {
503+
let (analysis, file_id) = single_file(
504+
r#"
505+
#[derive(Clone, Debug)]
506+
struct Foo {
507+
pub x: i32,
508+
pub y: i32,
509+
}"#,
510+
);
511+
512+
let highlights = &analysis
513+
.highlight_range(FileRange {
514+
file_id,
515+
range: TextRange::offset_len(82.into(), 1.into()), // "x"
516+
})
517+
.unwrap();
518+
519+
assert_eq!(highlights[0].tag, "field");
520+
}
478521
}

crates/rust-analyzer/src/caps.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ use lsp_types::{
77
CompletionOptions, DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability,
88
ImplementationProviderCapability, RenameOptions, RenameProviderCapability, SaveOptions,
99
SelectionRangeProviderCapability, SemanticTokensDocumentProvider, SemanticTokensLegend,
10-
SemanticTokensOptions, SemanticTokensServerCapabilities, ServerCapabilities,
11-
SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind,
12-
TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions,
10+
SemanticTokensOptions, ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability,
11+
TextDocumentSyncKind, TextDocumentSyncOptions, TypeDefinitionProviderCapability,
12+
WorkDoneProgressOptions,
1313
};
1414

1515
pub fn server_capabilities() -> ServerCapabilities {
@@ -60,7 +60,7 @@ pub fn server_capabilities() -> ServerCapabilities {
6060
execute_command_provider: None,
6161
workspace: None,
6262
call_hierarchy_provider: Some(CallHierarchyServerCapability::Simple(true)),
63-
semantic_tokens_provider: Some(SemanticTokensServerCapabilities::SemanticTokensOptions(
63+
semantic_tokens_provider: Some(
6464
SemanticTokensOptions {
6565
legend: SemanticTokensLegend {
6666
token_types: semantic_tokens::supported_token_types().iter().cloned().collect(),
@@ -71,9 +71,11 @@ pub fn server_capabilities() -> ServerCapabilities {
7171
},
7272

7373
document_provider: Some(SemanticTokensDocumentProvider::Bool(true)),
74-
..SemanticTokensOptions::default()
75-
},
76-
)),
74+
range_provider: Some(true),
75+
work_done_progress_options: Default::default(),
76+
}
77+
.into(),
78+
),
7779
experimental: Default::default(),
7880
}
7981
}

crates/rust-analyzer/src/main_loop.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,8 +527,9 @@ fn on_request(
527527
.on::<req::CallHierarchyPrepare>(handlers::handle_call_hierarchy_prepare)?
528528
.on::<req::CallHierarchyIncomingCalls>(handlers::handle_call_hierarchy_incoming)?
529529
.on::<req::CallHierarchyOutgoingCalls>(handlers::handle_call_hierarchy_outgoing)?
530-
.on::<req::Ssr>(handlers::handle_ssr)?
531530
.on::<req::SemanticTokensRequest>(handlers::handle_semantic_tokens)?
531+
.on::<req::SemanticTokensRangeRequest>(handlers::handle_semantic_tokens_range)?
532+
.on::<req::Ssr>(handlers::handle_ssr)?
532533
.finish();
533534
Ok(())
534535
}

crates/rust-analyzer/src/main_loop/handlers.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ use lsp_types::{
1717
Diagnostic, DocumentFormattingParams, DocumentHighlight, DocumentSymbol, FoldingRange,
1818
FoldingRangeParams, Hover, HoverContents, Location, MarkupContent, MarkupKind, Position,
1919
PrepareRenameResponse, Range, RenameParams, SemanticTokenModifier, SemanticTokenType,
20-
SemanticTokens, SemanticTokensParams, SemanticTokensResult, SymbolInformation,
21-
TextDocumentIdentifier, TextEdit, WorkspaceEdit,
20+
SemanticTokens, SemanticTokensParams, SemanticTokensRangeParams, SemanticTokensRangeResult,
21+
SemanticTokensResult, SymbolInformation, TextDocumentIdentifier, TextEdit, WorkspaceEdit,
2222
};
2323
use ra_ide::{
2424
AssistId, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind,
@@ -1092,3 +1092,25 @@ pub fn handle_semantic_tokens(
10921092

10931093
Ok(Some(tokens.into()))
10941094
}
1095+
1096+
pub fn handle_semantic_tokens_range(
1097+
world: WorldSnapshot,
1098+
params: SemanticTokensRangeParams,
1099+
) -> Result<Option<SemanticTokensRangeResult>> {
1100+
let _p = profile("handle_semantic_tokens_range");
1101+
1102+
let frange = (&params.text_document, params.range).try_conv_with(&world)?;
1103+
let line_index = world.analysis().file_line_index(frange.file_id)?;
1104+
1105+
let mut builder = SemanticTokensBuilder::default();
1106+
1107+
for h in world.analysis().highlight_range(frange)?.into_iter() {
1108+
let type_and_modifiers: (SemanticTokenType, Vec<SemanticTokenModifier>) = h.tag.conv();
1109+
let (token_type, token_modifiers) = type_and_modifiers.conv();
1110+
builder.push(h.range.conv_with(&line_index), token_type, token_modifiers);
1111+
}
1112+
1113+
let tokens = SemanticTokens { data: builder.build(), ..Default::default() };
1114+
1115+
Ok(Some(tokens.into()))
1116+
}

crates/rust-analyzer/src/req.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ pub use lsp_types::{
1212
DocumentSymbolResponse, FileSystemWatcher, Hover, InitializeResult, MessageType,
1313
PartialResultParams, ProgressParams, ProgressParamsValue, ProgressToken,
1414
PublishDiagnosticsParams, ReferenceParams, Registration, RegistrationParams, SelectionRange,
15-
SelectionRangeParams, SemanticTokensParams, SemanticTokensResult, ServerCapabilities,
16-
ShowMessageParams, SignatureHelp, SymbolKind, TextDocumentEdit, TextDocumentPositionParams,
17-
TextEdit, WorkDoneProgressParams, WorkspaceEdit, WorkspaceSymbolParams,
15+
SelectionRangeParams, SemanticTokensParams, SemanticTokensRangeParams,
16+
SemanticTokensRangeResult, SemanticTokensResult, ServerCapabilities, ShowMessageParams,
17+
SignatureHelp, SymbolKind, TextDocumentEdit, TextDocumentPositionParams, TextEdit,
18+
WorkDoneProgressParams, WorkspaceEdit, WorkspaceSymbolParams,
1819
};
1920

2021
pub enum AnalyzerStatus {}

0 commit comments

Comments
 (0)