Skip to content

Commit

Permalink
Merge #9678
Browse files Browse the repository at this point in the history
9678: Add Configuration for Highlight Related Feature r=kdelorey a=kdelorey

# Summary
Adds basic configuration that allows you to control when the highlight related feature is activated. You can control this for references, break points, exit points, and yield points.

Resolves #9618 

![config](https://user-images.githubusercontent.com/2295721/126728849-a38b560c-b687-42c1-9c41-7584ad718469.gif)


Co-authored-by: Kevin DeLorey <[email protected]>
  • Loading branch information
bors[bot] and kdelorey authored Jul 23, 2021
2 parents 1dd1814 + 5b9f173 commit 4107106
Show file tree
Hide file tree
Showing 7 changed files with 278 additions and 27 deletions.
217 changes: 212 additions & 5 deletions crates/ide/src/highlight_related.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ pub struct HighlightedRange {
pub access: Option<ReferenceAccess>,
}

#[derive(Default, Clone)]
pub struct HighlightRelatedConfig {
pub references: bool,
pub exit_points: bool,
pub break_points: bool,
pub yield_points: bool,
}

// Feature: Highlight Related
//
// Highlights constructs related to the thing under the cursor:
Expand All @@ -27,6 +35,7 @@ pub struct HighlightedRange {
// - if on a `break`, `loop`, `while` or `for` token, highlights all break points for that loop or block context
pub(crate) fn highlight_related(
sema: &Semantics<RootDatabase>,
config: HighlightRelatedConfig,
position: FilePosition,
) -> Option<Vec<HighlightedRange>> {
let _p = profile::span("highlight_related");
Expand All @@ -46,10 +55,13 @@ pub(crate) fn highlight_related(
})?;

match token.kind() {
T![return] | T![?] | T![->] => highlight_exit_points(sema, token),
T![await] | T![async] => highlight_yield_points(token),
T![break] | T![loop] | T![for] | T![while] => highlight_break_points(token),
_ => highlight_references(sema, &syntax, position),
T![return] | T![?] | T![->] if config.exit_points => highlight_exit_points(sema, token),
T![await] | T![async] if config.yield_points => highlight_yield_points(token),
T![break] | T![loop] | T![for] | T![while] if config.break_points => {
highlight_break_points(token)
}
_ if config.references => highlight_references(sema, &syntax, position),
_ => None,
}
}

Expand Down Expand Up @@ -260,8 +272,20 @@ mod tests {
use super::*;

fn check(ra_fixture: &str) {
let config = HighlightRelatedConfig {
break_points: true,
exit_points: true,
references: true,
yield_points: true,
};

check_with_config(ra_fixture, config);
}

fn check_with_config(ra_fixture: &str, config: HighlightRelatedConfig) {
let (analysis, pos, annotations) = fixture::annotations(ra_fixture);
let hls = analysis.highlight_related(pos).unwrap().unwrap();

let hls = analysis.highlight_related(config, pos).unwrap().unwrap_or(Vec::default());

let mut expected = annotations
.into_iter()
Expand Down Expand Up @@ -726,4 +750,187 @@ fn foo() {
"#,
);
}

#[test]
fn test_hl_disabled_ref_local() {
let config = HighlightRelatedConfig {
references: false,
break_points: true,
exit_points: true,
yield_points: true,
};

let ra_fixture = r#"
fn foo() {
let x$0 = 5;
let y = x * 2;
}"#;

check_with_config(ra_fixture, config);
}

#[test]
fn test_hl_disabled_ref_local_preserved_break() {
let config = HighlightRelatedConfig {
references: false,
break_points: true,
exit_points: true,
yield_points: true,
};

let ra_fixture = r#"
fn foo() {
let x$0 = 5;
let y = x * 2;
loop {
break;
}
}"#;

check_with_config(ra_fixture, config.clone());

let ra_fixture = r#"
fn foo() {
let x = 5;
let y = x * 2;
loop$0 {
// ^^^^
break;
// ^^^^^
}
}"#;

check_with_config(ra_fixture, config);
}

#[test]
fn test_hl_disabled_ref_local_preserved_yield() {
let config = HighlightRelatedConfig {
references: false,
break_points: true,
exit_points: true,
yield_points: true,
};

let ra_fixture = r#"
async fn foo() {
let x$0 = 5;
let y = x * 2;
0.await;
}"#;

check_with_config(ra_fixture, config.clone());

let ra_fixture = r#"
async fn foo() {
// ^^^^^
let x = 5;
let y = x * 2;
0.await$0;
// ^^^^^
}"#;

check_with_config(ra_fixture, config);
}

#[test]
fn test_hl_disabled_ref_local_preserved_exit() {
let config = HighlightRelatedConfig {
references: false,
break_points: true,
exit_points: true,
yield_points: true,
};

let ra_fixture = r#"
fn foo() -> i32 {
let x$0 = 5;
let y = x * 2;
if true {
return y;
}
0?
}"#;

check_with_config(ra_fixture, config.clone());

let ra_fixture = r#"
fn foo() ->$0 i32 {
let x = 5;
let y = x * 2;
if true {
return y;
// ^^^^^^
}
0?
// ^
"#;

check_with_config(ra_fixture, config);
}

#[test]
fn test_hl_disabled_break() {
let config = HighlightRelatedConfig {
references: true,
break_points: false,
exit_points: true,
yield_points: true,
};

let ra_fixture = r#"
fn foo() {
loop {
break$0;
}
}"#;

check_with_config(ra_fixture, config);
}

#[test]
fn test_hl_disabled_yield() {
let config = HighlightRelatedConfig {
references: true,
break_points: true,
exit_points: true,
yield_points: false,
};

let ra_fixture = r#"
async$0 fn foo() {
0.await;
}"#;

check_with_config(ra_fixture, config);
}

#[test]
fn test_hl_disabled_exit() {
let config = HighlightRelatedConfig {
references: true,
break_points: true,
exit_points: false,
yield_points: true,
};

let ra_fixture = r#"
fn foo() ->$0 i32 {
if true {
return -1;
}
42
}"#;

check_with_config(ra_fixture, config);
}
}
7 changes: 5 additions & 2 deletions crates/ide/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub use crate::{
expand_macro::ExpandedMacro,
file_structure::{StructureNode, StructureNodeKind},
folding_ranges::{Fold, FoldKind},
highlight_related::HighlightedRange,
highlight_related::{HighlightRelatedConfig, HighlightedRange},
hover::{HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult},
inlay_hints::{InlayHint, InlayHintsConfig, InlayKind},
join_lines::JoinLinesConfig,
Expand Down Expand Up @@ -496,9 +496,12 @@ impl Analysis {
/// Computes all ranges to highlight for a given item in a file.
pub fn highlight_related(
&self,
config: HighlightRelatedConfig,
position: FilePosition,
) -> Cancellable<Option<Vec<HighlightedRange>>> {
self.with_db(|db| highlight_related::highlight_related(&Semantics::new(db), position))
self.with_db(|db| {
highlight_related::highlight_related(&Semantics::new(db), config, position)
})
}

/// Computes syntax highlighting for the given file range.
Expand Down
22 changes: 20 additions & 2 deletions crates/rust-analyzer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use std::{ffi::OsString, iter, path::PathBuf};

use flycheck::FlycheckConfig;
use ide::{
AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, HoverDocFormat,
InlayHintsConfig, JoinLinesConfig,
AssistConfig, CompletionConfig, DiagnosticsConfig, HighlightRelatedConfig, HoverConfig,
HoverDocFormat, InlayHintsConfig, JoinLinesConfig,
};
use ide_db::helpers::{
insert_use::{ImportGranularity, InsertUseConfig, PrefixKind},
Expand Down Expand Up @@ -147,6 +147,15 @@ config_data! {
/// also need to add the folders to Code's `files.watcherExclude`.
files_excludeDirs: Vec<PathBuf> = "[]",

/// Enables highlighting of related references while hovering your mouse above any identifier.
highlightRelated_references: bool = "true",
/// Enables highlighting of all exit points while hovering your mouse above any `return`, `?`, or return type arrow (`->`).
highlightRelated_exitPoints: bool = "true",
/// Enables highlighting of related references while hovering your mouse `break`, `loop`, `while`, or `for` keywords.
highlightRelated_breakPoints: bool = "true",
/// Enables highlighting of all break points for a loop or block context while hovering your mouse above any `async` or `await` keywords.
highlightRelated_yieldPoints: bool = "true",

/// Use semantic tokens for strings.
///
/// In some editors (e.g. vscode) semantic tokens override other highlighting grammars.
Expand Down Expand Up @@ -852,6 +861,15 @@ impl Config {
false
)
}

pub fn highlight_related(&self) -> HighlightRelatedConfig {
HighlightRelatedConfig {
references: self.data.highlightRelated_references,
break_points: self.data.highlightRelated_breakPoints,
exit_points: self.data.highlightRelated_exitPoints,
yield_points: self.data.highlightRelated_yieldPoints,
}
}
}

#[derive(Deserialize, Debug, Clone)]
Expand Down
2 changes: 1 addition & 1 deletion crates/rust-analyzer/src/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1188,7 +1188,7 @@ pub(crate) fn handle_document_highlight(
let position = from_proto::file_position(&snap, params.text_document_position_params)?;
let line_index = snap.file_line_index(position.file_id)?;

let refs = match snap.analysis.highlight_related(position)? {
let refs = match snap.analysis.highlight_related(snap.config.highlight_related(), position)? {
None => return Ok(None),
Some(refs) => refs,
};
Expand Down
20 changes: 20 additions & 0 deletions docs/user/generated_config.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,26 @@ These directories will be ignored by rust-analyzer. They are
relative to the workspace root, and globs are not supported. You may
also need to add the folders to Code's `files.watcherExclude`.
--
[[rust-analyzer.highlightRelated.references]]rust-analyzer.highlightRelated.references (default: `true`)::
+
--
Enables highlighting of related references while hovering your mouse above any identifier.
--
[[rust-analyzer.highlightRelated.exitPoints]]rust-analyzer.highlightRelated.exitPoints (default: `true`)::
+
--
Enables highlighting of all exit points while hovering your mouse above any `return`, `?`, or return type arrow (`->`).
--
[[rust-analyzer.highlightRelated.breakPoints]]rust-analyzer.highlightRelated.breakPoints (default: `true`)::
+
--
Enables highlighting of related references while hovering your mouse `break`, `loop`, `while`, or `for` keywords.
--
[[rust-analyzer.highlightRelated.yieldPoints]]rust-analyzer.highlightRelated.yieldPoints (default: `true`)::
+
--
Enables highlighting of all break points for a loop or block context while hovering your mouse above any `async` or `await` keywords.
--
[[rust-analyzer.highlighting.strings]]rust-analyzer.highlighting.strings (default: `true`)::
+
--
Expand Down
20 changes: 20 additions & 0 deletions editors/code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,26 @@
"type": "string"
}
},
"rust-analyzer.highlightRelated.references": {
"markdownDescription": "Enables highlighting of related references while hovering your mouse above any identifier.",
"default": true,
"type": "boolean"
},
"rust-analyzer.highlightRelated.exitPoints": {
"markdownDescription": "Enables highlighting of all exit points while hovering your mouse above any `return`, `?`, or return type arrow (`->`).",
"default": true,
"type": "boolean"
},
"rust-analyzer.highlightRelated.breakPoints": {
"markdownDescription": "Enables highlighting of related references while hovering your mouse `break`, `loop`, `while`, or `for` keywords.",
"default": true,
"type": "boolean"
},
"rust-analyzer.highlightRelated.yieldPoints": {
"markdownDescription": "Enables highlighting of all break points for a loop or block context while hovering your mouse above any `async` or `await` keywords.",
"default": true,
"type": "boolean"
},
"rust-analyzer.highlighting.strings": {
"markdownDescription": "Use semantic tokens for strings.\n\nIn some editors (e.g. vscode) semantic tokens override other highlighting grammars.\nBy disabling semantic tokens for strings, other grammars can be used to highlight\ntheir contents.",
"default": true,
Expand Down
Loading

0 comments on commit 4107106

Please sign in to comment.