Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--Cargo.lock1
-rw-r--r--crates/ide-assists/src/handlers/extract_function.rs8
-rw-r--r--crates/ide-assists/src/handlers/remove_unused_imports.rs2
-rw-r--r--crates/ide-db/Cargo.toml1
-rw-r--r--crates/ide-db/src/search.rs85
-rw-r--r--crates/ide/src/highlight_related.rs83
-rw-r--r--crates/ide/src/references.rs123
-rw-r--r--crates/rust-analyzer/src/handlers/request.rs6
-rw-r--r--crates/rust-analyzer/src/lsp/to_proto.rs11
9 files changed, 188 insertions, 132 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 20bd36b894..a6e460134f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -695,6 +695,7 @@ version = "0.0.0"
dependencies = [
"arrayvec",
"base-db",
+ "bitflags 2.4.2",
"cov-mark",
"crossbeam-channel",
"either",
diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs
index d111005c2e..34326294d2 100644
--- a/crates/ide-assists/src/handlers/extract_function.rs
+++ b/crates/ide-assists/src/handlers/extract_function.rs
@@ -1149,8 +1149,14 @@ fn reference_is_exclusive(
node: &dyn HasTokenAtOffset,
ctx: &AssistContext<'_>,
) -> bool {
+ // FIXME: this quite an incorrect way to go about doing this :-)
+ // `FileReference` is an IDE-type --- it encapsulates data communicated to the human,
+ // but doesn't necessary fully reflect all the intricacies of the underlying language semantics
+ // The correct approach here would be to expose this entire analysis as a method on some hir
+ // type. Something like `body.free_variables(statement_range)`.
+
// we directly modify variable with set: `n = 0`, `n += 1`
- if reference.category == Some(ReferenceCategory::Write) {
+ if reference.category.contains(ReferenceCategory::WRITE) {
return true;
}
diff --git a/crates/ide-assists/src/handlers/remove_unused_imports.rs b/crates/ide-assists/src/handlers/remove_unused_imports.rs
index d67b259d2f..0f0f13bbc8 100644
--- a/crates/ide-assists/src/handlers/remove_unused_imports.rs
+++ b/crates/ide-assists/src/handlers/remove_unused_imports.rs
@@ -145,7 +145,7 @@ fn used_once_in_scope(ctx: &AssistContext<'_>, def: Definition, scopes: &Vec<Sea
for scope in scopes {
let mut search_non_import = |_, r: FileReference| {
// The import itself is a use; we must skip that.
- if r.category != Some(ReferenceCategory::Import) {
+ if !r.category.contains(ReferenceCategory::IMPORT) {
found = true;
true
} else {
diff --git a/crates/ide-db/Cargo.toml b/crates/ide-db/Cargo.toml
index 071e1b4717..9a6826a5c4 100644
--- a/crates/ide-db/Cargo.toml
+++ b/crates/ide-db/Cargo.toml
@@ -26,6 +26,7 @@ indexmap.workspace = true
memchr = "2.6.4"
triomphe.workspace = true
nohash-hasher.workspace = true
+bitflags.workspace = true
# local deps
base-db.workspace = true
diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs
index a3ecc10360..cb103313c9 100644
--- a/crates/ide-db/src/search.rs
+++ b/crates/ide-db/src/search.rs
@@ -64,7 +64,7 @@ pub struct FileReference {
pub range: TextRange,
/// The node of the reference in the (macro-)file
pub name: FileReferenceNode,
- pub category: Option<ReferenceCategory>,
+ pub category: ReferenceCategory,
}
#[derive(Debug, Clone)]
@@ -124,17 +124,16 @@ impl FileReferenceNode {
}
}
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub enum ReferenceCategory {
- // FIXME: Add this variant and delete the `retain_adt_literal_usages` function.
- // Create
- Write,
- Read,
- Import,
- // FIXME: Some day should be able to search in doc comments. Would probably
- // need to switch from enum to bitflags then?
- // DocComment
- Test,
+bitflags::bitflags! {
+ #[derive(Copy, Clone, Default, PartialEq, Eq, Hash, Debug)]
+ pub struct ReferenceCategory: u8 {
+ // FIXME: Add this variant and delete the `retain_adt_literal_usages` function.
+ // const CREATE = 1 << 0;
+ const WRITE = 1 << 0;
+ const READ = 1 << 1;
+ const IMPORT = 1 << 2;
+ const TEST = 1 << 3;
+ }
}
/// Generally, `search_scope` returns files that might contain references for the element.
@@ -660,7 +659,7 @@ impl<'a> FindUsages<'a> {
let reference = FileReference {
range,
name: FileReferenceNode::NameRef(name_ref.clone()),
- category: None,
+ category: ReferenceCategory::empty(),
};
sink(file_id, reference)
}
@@ -676,10 +675,15 @@ impl<'a> FindUsages<'a> {
match NameRefClass::classify(self.sema, name_ref) {
Some(NameRefClass::Definition(def @ Definition::Module(_))) if def == self.def => {
let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
+ let category = if is_name_ref_in_import(name_ref) {
+ ReferenceCategory::IMPORT
+ } else {
+ ReferenceCategory::empty()
+ };
let reference = FileReference {
range,
name: FileReferenceNode::NameRef(name_ref.clone()),
- category: is_name_ref_in_import(name_ref).then_some(ReferenceCategory::Import),
+ category,
};
sink(file_id, reference)
}
@@ -700,7 +704,7 @@ impl<'a> FindUsages<'a> {
let reference = FileReference {
range,
name: FileReferenceNode::FormatStringEntry(token, range),
- category: Some(ReferenceCategory::Read),
+ category: ReferenceCategory::READ,
};
sink(file_id, reference)
}
@@ -719,7 +723,7 @@ impl<'a> FindUsages<'a> {
let reference = FileReference {
range,
name: FileReferenceNode::Lifetime(lifetime.clone()),
- category: None,
+ category: ReferenceCategory::empty(),
};
sink(file_id, reference)
}
@@ -817,7 +821,7 @@ impl<'a> FindUsages<'a> {
range,
name: FileReferenceNode::Name(name.clone()),
// FIXME: mutable patterns should have `Write` access
- category: Some(ReferenceCategory::Read),
+ category: ReferenceCategory::READ,
};
sink(file_id, reference)
}
@@ -826,7 +830,7 @@ impl<'a> FindUsages<'a> {
let reference = FileReference {
range,
name: FileReferenceNode::Name(name.clone()),
- category: None,
+ category: ReferenceCategory::empty(),
};
sink(file_id, reference)
}
@@ -851,7 +855,7 @@ impl<'a> FindUsages<'a> {
let reference = FileReference {
range,
name: FileReferenceNode::Name(name.clone()),
- category: None,
+ category: ReferenceCategory::empty(),
};
sink(file_id, reference)
}
@@ -875,38 +879,41 @@ impl ReferenceCategory {
sema: &Semantics<'_, RootDatabase>,
def: &Definition,
r: &ast::NameRef,
- ) -> Option<ReferenceCategory> {
+ ) -> ReferenceCategory {
+ let mut result = ReferenceCategory::empty();
if is_name_ref_in_test(sema, r) {
- return Some(ReferenceCategory::Test);
+ result |= ReferenceCategory::TEST;
}
// Only Locals and Fields have accesses for now.
if !matches!(def, Definition::Local(_) | Definition::Field(_)) {
- return is_name_ref_in_import(r).then_some(ReferenceCategory::Import);
+ if is_name_ref_in_import(r) {
+ result |= ReferenceCategory::IMPORT;
+ }
+ return result;
}
let mode = r.syntax().ancestors().find_map(|node| {
- match_ast! {
- match node {
- ast::BinExpr(expr) => {
- if matches!(expr.op_kind()?, ast::BinaryOp::Assignment { .. }) {
- // If the variable or field ends on the LHS's end then it's a Write (covers fields and locals).
- // FIXME: This is not terribly accurate.
- if let Some(lhs) = expr.lhs() {
- if lhs.syntax().text_range().end() == r.syntax().text_range().end() {
- return Some(ReferenceCategory::Write);
+ match_ast! {
+ match node {
+ ast::BinExpr(expr) => {
+ if matches!(expr.op_kind()?, ast::BinaryOp::Assignment { .. }) {
+ // If the variable or field ends on the LHS's end then it's a Write
+ // (covers fields and locals). FIXME: This is not terribly accurate.
+ if let Some(lhs) = expr.lhs() {
+ if lhs.syntax().text_range().end() == r.syntax().text_range().end() {
+ return Some(ReferenceCategory::WRITE)
+ }
}
}
- }
- Some(ReferenceCategory::Read)
- },
- _ => None
+ Some(ReferenceCategory::READ)
+ },
+ _ => None,
+ }
}
- }
- });
+ }).unwrap_or(ReferenceCategory::READ);
- // Default Locals and Fields to read
- mode.or(Some(ReferenceCategory::Read))
+ result | mode
}
}
diff --git a/crates/ide/src/highlight_related.rs b/crates/ide/src/highlight_related.rs
index e20e0b67f4..6f32ce76b2 100644
--- a/crates/ide/src/highlight_related.rs
+++ b/crates/ide/src/highlight_related.rs
@@ -26,7 +26,7 @@ pub struct HighlightedRange {
// FIXME: This needs to be more precise. Reference category makes sense only
// for references, but we also have defs. And things like exit points are
// neither.
- pub category: Option<ReferenceCategory>,
+ pub category: ReferenceCategory,
}
#[derive(Default, Clone)]
@@ -113,7 +113,11 @@ fn highlight_closure_captures(
range,
category,
});
- let category = local.is_mut(sema.db).then_some(ReferenceCategory::Write);
+ let category = if local.is_mut(sema.db) {
+ ReferenceCategory::WRITE
+ } else {
+ ReferenceCategory::empty()
+ };
local
.sources(sema.db)
.into_iter()
@@ -137,7 +141,9 @@ fn highlight_references(
{
match resolution.map(Definition::from) {
Some(def) => iter::once(def).collect(),
- None => return Some(vec![HighlightedRange { range, category: None }]),
+ None => {
+ return Some(vec![HighlightedRange { range, category: ReferenceCategory::empty() }])
+ }
}
} else {
find_defs(sema, token.clone())
@@ -211,7 +217,11 @@ fn highlight_references(
// highlight the defs themselves
match def {
Definition::Local(local) => {
- let category = local.is_mut(sema.db).then_some(ReferenceCategory::Write);
+ let category = if local.is_mut(sema.db) {
+ ReferenceCategory::WRITE
+ } else {
+ ReferenceCategory::empty()
+ };
local
.sources(sema.db)
.into_iter()
@@ -238,8 +248,11 @@ fn highlight_references(
continue;
}
let hl_range = nav.focus_range.map(|range| {
- let category = matches!(def, Definition::Local(l) if l.is_mut(sema.db))
- .then_some(ReferenceCategory::Write);
+ let category = if matches!(def, Definition::Local(l) if l.is_mut(sema.db)) {
+ ReferenceCategory::WRITE
+ } else {
+ ReferenceCategory::empty()
+ };
HighlightedRange { range, category }
});
if let Some(hl_range) = hl_range {
@@ -272,24 +285,30 @@ fn highlight_exit_points(
def_ranges
.into_iter()
.flatten()
- .map(|range| HighlightedRange { category: None, range }),
+ .map(|range| HighlightedRange { category: ReferenceCategory::empty(), range }),
);
let body = body?;
walk_expr(&body, &mut |expr| match expr {
ast::Expr::ReturnExpr(expr) => {
if let Some(token) = expr.return_token() {
- highlights.push(HighlightedRange { category: None, range: token.text_range() });
+ highlights.push(HighlightedRange {
+ category: ReferenceCategory::empty(),
+ range: token.text_range(),
+ });
}
}
ast::Expr::TryExpr(try_) => {
if let Some(token) = try_.question_mark_token() {
- highlights.push(HighlightedRange { category: None, range: token.text_range() });
+ highlights.push(HighlightedRange {
+ category: ReferenceCategory::empty(),
+ range: token.text_range(),
+ });
}
}
ast::Expr::MethodCallExpr(_) | ast::Expr::CallExpr(_) | ast::Expr::MacroExpr(_) => {
if sema.type_of_expr(&expr).map_or(false, |ty| ty.original.is_never()) {
highlights.push(HighlightedRange {
- category: None,
+ category: ReferenceCategory::empty(),
range: expr.syntax().text_range(),
});
}
@@ -309,7 +328,7 @@ fn highlight_exit_points(
.map_or_else(|| tail.syntax().text_range(), |tok| tok.text_range()),
_ => tail.syntax().text_range(),
};
- highlights.push(HighlightedRange { category: None, range })
+ highlights.push(HighlightedRange { category: ReferenceCategory::empty(), range })
});
}
Some(highlights)
@@ -354,7 +373,9 @@ fn highlight_break_points(token: SyntaxToken) -> Option<Vec<HighlightedRange>> {
token.map(|tok| tok.text_range()),
label.as_ref().map(|it| it.syntax().text_range()),
);
- highlights.extend(range.map(|range| HighlightedRange { category: None, range }));
+ highlights.extend(
+ range.map(|range| HighlightedRange { category: ReferenceCategory::empty(), range }),
+ );
for_each_break_and_continue_expr(label, body, &mut |expr| {
let range: Option<TextRange> = match (cursor_token_kind, expr) {
(T![for] | T![while] | T![loop] | T![break], ast::Expr::BreakExpr(break_)) => {
@@ -372,7 +393,9 @@ fn highlight_break_points(token: SyntaxToken) -> Option<Vec<HighlightedRange>> {
),
_ => None,
};
- highlights.extend(range.map(|range| HighlightedRange { category: None, range }));
+ highlights.extend(
+ range.map(|range| HighlightedRange { category: ReferenceCategory::empty(), range }),
+ );
});
Some(highlights)
}
@@ -430,14 +453,18 @@ fn highlight_yield_points(token: SyntaxToken) -> Option<Vec<HighlightedRange>> {
async_token: Option<SyntaxToken>,
body: Option<ast::Expr>,
) -> Option<Vec<HighlightedRange>> {
- let mut highlights =
- vec![HighlightedRange { category: None, range: async_token?.text_range() }];
+ let mut highlights = vec![HighlightedRange {
+ category: ReferenceCategory::empty(),
+ range: async_token?.text_range(),
+ }];
if let Some(body) = body {
walk_expr(&body, &mut |expr| {
if let ast::Expr::AwaitExpr(expr) = expr {
if let Some(token) = expr.await_token() {
- highlights
- .push(HighlightedRange { category: None, range: token.text_range() });
+ highlights.push(HighlightedRange {
+ category: ReferenceCategory::empty(),
+ range: token.text_range(),
+ });
}
}
});
@@ -481,6 +508,8 @@ fn find_defs(sema: &Semantics<'_, RootDatabase>, token: SyntaxToken) -> FxHashSe
#[cfg(test)]
mod tests {
+ use itertools::Itertools;
+
use crate::fixture;
use super::*;
@@ -504,28 +533,18 @@ mod tests {
let hls = analysis.highlight_related(config, pos).unwrap().unwrap_or_default();
- let mut expected = annotations
- .into_iter()
- .map(|(r, access)| (r.range, (!access.is_empty()).then_some(access)))
- .collect::<Vec<_>>();
+ let mut expected =
+ annotations.into_iter().map(|(r, access)| (r.range, access)).collect::<Vec<_>>();
- let mut actual = hls
+ let mut actual: Vec<(TextRange, String)> = hls
.into_iter()
.map(|hl| {
(
hl.range,
- hl.category.map(|it| {
- match it {
- ReferenceCategory::Read => "read",
- ReferenceCategory::Write => "write",
- ReferenceCategory::Import => "import",
- ReferenceCategory::Test => "test",
- }
- .to_owned()
- }),
+ hl.category.iter_names().map(|(name, _flag)| name.to_lowercase()).join(","),
)
})
- .collect::<Vec<_>>();
+ .collect();
actual.sort_by_key(|(range, _)| range.start());
expected.sort_by_key(|(range, _)| range.start());
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index fef2aba3c6..01af864cdf 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -30,7 +30,7 @@ use crate::{FilePosition, NavigationTarget, TryToNav};
#[derive(Debug, Clone)]
pub struct ReferenceSearchResult {
pub declaration: Option<Declaration>,
- pub references: IntMap<FileId, Vec<(TextRange, Option<ReferenceCategory>)>>,
+ pub references: IntMap<FileId, Vec<(TextRange, ReferenceCategory)>>,
}
#[derive(Debug, Clone)]
@@ -66,7 +66,7 @@ pub(crate) fn find_all_refs(
retain_adt_literal_usages(&mut usages, def, sema);
}
- let mut references = usages
+ let mut references: IntMap<FileId, Vec<(TextRange, ReferenceCategory)>> = usages
.into_iter()
.map(|(file_id, refs)| {
(
@@ -77,7 +77,7 @@ pub(crate) fn find_all_refs(
.collect(),
)
})
- .collect::<IntMap<_, Vec<_>>>();
+ .collect();
let declaration = match def {
Definition::Module(module) => {
Some(NavigationTarget::from_module_to_decl(sema.db, module))
@@ -93,7 +93,7 @@ pub(crate) fn find_all_refs(
references
.entry(extra_ref.file_id)
.or_default()
- .push((extra_ref.focus_or_full_range(), None));
+ .push((extra_ref.focus_or_full_range(), ReferenceCategory::empty()));
}
Declaration {
is_mut: matches!(def, Definition::Local(l) if l.is_mut(sema.db)),
@@ -300,7 +300,7 @@ fn is_lit_name_ref(name_ref: &ast::NameRef) -> bool {
#[cfg(test)]
mod tests {
use expect_test::{expect, Expect};
- use ide_db::{base_db::FileId, search::ReferenceCategory};
+ use ide_db::base_db::FileId;
use stdx::format_to;
use crate::{fixture, SearchScope};
@@ -324,7 +324,7 @@ fn test() {
test_func Function FileId(0) 0..17 3..12
FileId(0) 35..44
- FileId(0) 75..84 Test
+ FileId(0) 75..84 test
"#]],
);
@@ -345,7 +345,28 @@ fn test() {
test_func Function FileId(0) 0..17 3..12
FileId(0) 35..44
- FileId(0) 96..105 Test
+ FileId(0) 96..105 test
+ "#]],
+ );
+ }
+
+ #[test]
+ fn test_access() {
+ check(
+ r#"
+struct S { f$0: u32 }
+
+#[test]
+fn test() {
+ let mut x = S { f: 92 };
+ x.f = 92;
+}
+"#,
+ expect![[r#"
+ f Field FileId(0) 11..17 11..12
+
+ FileId(0) 61..62 read test
+ FileId(0) 76..77 write test
"#]],
);
}
@@ -600,12 +621,12 @@ fn main() {
i = 5;
}"#,
expect![[r#"
- i Local FileId(0) 20..25 24..25 Write
+ i Local FileId(0) 20..25 24..25 write
- FileId(0) 50..51 Write
- FileId(0) 54..55 Read
- FileId(0) 76..77 Write
- FileId(0) 94..95 Write
+ FileId(0) 50..51 write
+ FileId(0) 54..55 read
+ FileId(0) 76..77 write
+ FileId(0) 94..95 write
"#]],
);
}
@@ -626,8 +647,8 @@ fn bar() {
expect![[r#"
spam Local FileId(0) 19..23 19..23
- FileId(0) 34..38 Read
- FileId(0) 41..45 Read
+ FileId(0) 34..38 read
+ FileId(0) 41..45 read
"#]],
);
}
@@ -641,7 +662,7 @@ fn foo(i : u32) -> u32 { i$0 }
expect![[r#"
i ValueParam FileId(0) 7..8 7..8
- FileId(0) 25..26 Read
+ FileId(0) 25..26 read
"#]],
);
}
@@ -655,7 +676,7 @@ fn foo(i$0 : u32) -> u32 { i }
expect![[r#"
i ValueParam FileId(0) 7..8 7..8
- FileId(0) 25..26 Read
+ FileId(0) 25..26 read
"#]],
);
}
@@ -676,7 +697,7 @@ fn main(s: Foo) {
expect![[r#"
spam Field FileId(0) 17..30 21..25
- FileId(0) 67..71 Read
+ FileId(0) 67..71 read
"#]],
);
}
@@ -824,7 +845,7 @@ pub struct Foo {
expect![[r#"
foo Module FileId(0) 0..8 4..7
- FileId(0) 14..17 Import
+ FileId(0) 14..17 import
"#]],
);
}
@@ -842,7 +863,7 @@ use self$0;
expect![[r#"
foo Module FileId(0) 0..8 4..7
- FileId(1) 4..8 Import
+ FileId(1) 4..8 import
"#]],
);
}
@@ -857,7 +878,7 @@ use self$0;
expect![[r#"
Module FileId(0) 0..10
- FileId(0) 4..8 Import
+ FileId(0) 4..8 import
"#]],
);
}
@@ -885,7 +906,7 @@ pub(super) struct Foo$0 {
expect![[r#"
Foo Struct FileId(2) 0..41 18..21 some
- FileId(1) 20..23 Import
+ FileId(1) 20..23 import
FileId(1) 47..50
"#]],
);
@@ -960,10 +981,10 @@ fn foo() {
}
"#,
expect![[r#"
- i Local FileId(0) 19..24 23..24 Write
+ i Local FileId(0) 19..24 23..24 write
- FileId(0) 34..35 Write
- FileId(0) 38..39 Read
+ FileId(0) 34..35 write
+ FileId(0) 38..39 read
"#]],
);
}
@@ -984,8 +1005,8 @@ fn foo() {
expect![[r#"
f Field FileId(0) 15..21 15..16
- FileId(0) 55..56 Read
- FileId(0) 68..69 Write
+ FileId(0) 55..56 read
+ FileId(0) 68..69 write
"#]],
);
}
@@ -1002,7 +1023,7 @@ fn foo() {
expect![[r#"
i Local FileId(0) 19..20 19..20
- FileId(0) 26..27 Write
+ FileId(0) 26..27 write
"#]],
);
}
@@ -1048,7 +1069,7 @@ fn g() { f(); }
expect![[r#"
f Function FileId(0) 22..31 25..26
- FileId(1) 11..12 Import
+ FileId(1) 11..12 import
FileId(1) 24..25
"#]],
);
@@ -1071,7 +1092,7 @@ fn f(s: S) {
expect![[r#"
field Field FileId(0) 15..24 15..20
- FileId(0) 68..73 Read
+ FileId(0) 68..73 read
"#]],
);
}
@@ -1095,7 +1116,7 @@ fn f(e: En) {
expect![[r#"
field Field FileId(0) 32..41 32..37
- FileId(0) 102..107 Read
+ FileId(0) 102..107 read
"#]],
);
}
@@ -1119,7 +1140,7 @@ fn f() -> m::En {
expect![[r#"
field Field FileId(0) 56..65 56..61
- FileId(0) 125..130 Read
+ FileId(0) 125..130 read
"#]],
);
}
@@ -1144,8 +1165,8 @@ impl Foo {
expect![[r#"
self SelfParam FileId(0) 47..51 47..51
- FileId(0) 71..75 Read
- FileId(0) 152..156 Read
+ FileId(0) 71..75 read
+ FileId(0) 152..156 read
"#]],
);
}
@@ -1165,7 +1186,7 @@ impl Foo {
expect![[r#"
self SelfParam FileId(0) 47..51 47..51
- FileId(0) 63..67 Read
+ FileId(0) 63..67 read
"#]],
);
}
@@ -1185,16 +1206,16 @@ impl Foo {
if let Some(decl) = refs.declaration {
format_to!(actual, "{}", decl.nav.debug_render());
if decl.is_mut {
- format_to!(actual, " {:?}", ReferenceCategory::Write)
+ format_to!(actual, " write",)
}
actual += "\n\n";
}
for (file_id, references) in &refs.references {
- for (range, access) in references {
+ for (range, category) in references {
format_to!(actual, "{:?} {:?}", file_id, range);
- if let Some(access) = access {
- format_to!(actual, " {:?}", access);
+ for (name, _flag) in category.iter_names() {
+ format_to!(actual, " {}", name.to_lowercase());
}
actual += "\n";
}
@@ -1281,7 +1302,7 @@ fn main() {
expect![[r#"
a Local FileId(0) 59..60 59..60
- FileId(0) 80..81 Read
+ FileId(0) 80..81 read
"#]],
);
}
@@ -1299,7 +1320,7 @@ fn main() {
expect![[r#"
a Local FileId(0) 59..60 59..60
- FileId(0) 80..81 Read
+ FileId(0) 80..81 read
"#]],
);
}
@@ -1479,7 +1500,7 @@ fn test$0() {
expect![[r#"
test Function FileId(0) 0..33 11..15
- FileId(0) 24..28 Test
+ FileId(0) 24..28 test
"#]],
);
}
@@ -1538,9 +1559,9 @@ pub use level1::Foo;
expect![[r#"
Foo Struct FileId(0) 0..15 11..14
- FileId(1) 16..19 Import
- FileId(2) 16..19 Import
- FileId(3) 16..19 Import
+ FileId(1) 16..19 import
+ FileId(2) 16..19 import
+ FileId(3) 16..19 import
"#]],
);
}
@@ -1568,7 +1589,7 @@ lib::foo!();
expect![[r#"
foo Macro FileId(1) 0..61 29..32
- FileId(0) 46..49 Import
+ FileId(0) 46..49 import
FileId(2) 0..3
FileId(3) 5..8
"#]],
@@ -1731,7 +1752,7 @@ struct Foo;
expect![[r#"
derive_identity Derive FileId(2) 1..107 45..60
- FileId(0) 17..31 Import
+ FileId(0) 17..31 import
FileId(0) 56..70
"#]],
);
@@ -2055,7 +2076,7 @@ fn method() {}
expect![[r#"
method Field FileId(0) 60..70 60..66
- FileId(0) 136..142 Read
+ FileId(0) 136..142 read
"#]],
);
check(
@@ -2101,7 +2122,7 @@ fn method() {}
expect![[r#"
method Field FileId(0) 60..70 60..66
- FileId(0) 136..142 Read
+ FileId(0) 136..142 read
"#]],
);
check(
@@ -2160,9 +2181,9 @@ fn test() {
expect![[r#"
a Local FileId(0) 20..21 20..21
- FileId(0) 56..57 Read
- FileId(0) 60..61 Read
- FileId(0) 68..69 Read
+ FileId(0) 56..57 read
+ FileId(0) 60..61 read
+ FileId(0) 68..69 read
"#]],
);
}
diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs
index 06c9816632..9c86704ba3 100644
--- a/crates/rust-analyzer/src/handlers/request.rs
+++ b/crates/rust-analyzer/src/handlers/request.rs
@@ -1164,8 +1164,8 @@ pub(crate) fn handle_references(
.flat_map(|(file_id, refs)| {
refs.into_iter()
.filter(|&(_, category)| {
- (!exclude_imports || category != Some(ReferenceCategory::Import))
- && (!exclude_tests || category != Some(ReferenceCategory::Test))
+ (!exclude_imports || !category.contains(ReferenceCategory::IMPORT))
+ && (!exclude_tests || !category.contains(ReferenceCategory::TEST))
})
.map(move |(range, _)| FileRange { file_id, range })
})
@@ -1452,7 +1452,7 @@ pub(crate) fn handle_document_highlight(
.into_iter()
.map(|ide::HighlightedRange { range, category }| lsp_types::DocumentHighlight {
range: to_proto::range(&line_index, range),
- kind: category.and_then(to_proto::document_highlight_kind),
+ kind: to_proto::document_highlight_kind(category),
})
.collect();
Ok(Some(res))
diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs
index 7e03458c52..d02f4612dc 100644
--- a/crates/rust-analyzer/src/lsp/to_proto.rs
+++ b/crates/rust-analyzer/src/lsp/to_proto.rs
@@ -92,12 +92,13 @@ pub(crate) fn structure_node_kind(kind: StructureNodeKind) -> lsp_types::SymbolK
pub(crate) fn document_highlight_kind(
category: ReferenceCategory,
) -> Option<lsp_types::DocumentHighlightKind> {
- match category {
- ReferenceCategory::Read => Some(lsp_types::DocumentHighlightKind::READ),
- ReferenceCategory::Write => Some(lsp_types::DocumentHighlightKind::WRITE),
- ReferenceCategory::Import => None,
- ReferenceCategory::Test => None,
+ if category.contains(ReferenceCategory::WRITE) {
+ return Some(lsp_types::DocumentHighlightKind::WRITE);
}
+ if category.contains(ReferenceCategory::READ) {
+ return Some(lsp_types::DocumentHighlightKind::READ);
+ }
+ None
}
pub(crate) fn diagnostic_severity(severity: Severity) -> lsp_types::DiagnosticSeverity {