Auto merge of #14849 - alibektas:14557n, r=Veykril
enhancement : using doc aliases to search workspace symbols ( fixes #14557 ) Doc aliases are now visible among symbols and can be used for searching.
This commit is contained in:
commit
8589a2d843
@ -20,6 +20,7 @@ pub struct FileSymbol {
|
||||
pub def: ModuleDef,
|
||||
pub loc: DeclarationLocation,
|
||||
pub container_name: Option<SmolStr>,
|
||||
pub is_alias: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
@ -249,46 +250,69 @@ fn push_decl<L>(&mut self, id: L)
|
||||
<L as Lookup>::Data: HasSource,
|
||||
<<L as Lookup>::Data as HasSource>::Value: HasName,
|
||||
{
|
||||
self.push_file_symbol(|s| {
|
||||
let loc = id.lookup(s.db.upcast());
|
||||
let source = loc.source(s.db.upcast());
|
||||
let name_node = source.value.name()?;
|
||||
Some(FileSymbol {
|
||||
name: name_node.text().into(),
|
||||
def: ModuleDef::from(id.into()),
|
||||
container_name: s.current_container_name.clone(),
|
||||
loc: DeclarationLocation {
|
||||
hir_file_id: source.file_id,
|
||||
ptr: SyntaxNodePtr::new(source.value.syntax()),
|
||||
name_ptr: SyntaxNodePtr::new(name_node.syntax()),
|
||||
},
|
||||
})
|
||||
})
|
||||
let loc = id.lookup(self.db.upcast());
|
||||
let source = loc.source(self.db.upcast());
|
||||
let Some(name_node) = source.value.name() else { return };
|
||||
let def = ModuleDef::from(id.into());
|
||||
let dec_loc = DeclarationLocation {
|
||||
hir_file_id: source.file_id,
|
||||
ptr: SyntaxNodePtr::new(source.value.syntax()),
|
||||
name_ptr: SyntaxNodePtr::new(name_node.syntax()),
|
||||
};
|
||||
|
||||
if let Some(attrs) = def.attrs(self.db) {
|
||||
for alias in attrs.doc_aliases() {
|
||||
self.symbols.push(FileSymbol {
|
||||
name: alias,
|
||||
def,
|
||||
loc: dec_loc.clone(),
|
||||
container_name: self.current_container_name.clone(),
|
||||
is_alias: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
self.symbols.push(FileSymbol {
|
||||
name: name_node.text().into(),
|
||||
def,
|
||||
container_name: self.current_container_name.clone(),
|
||||
loc: dec_loc,
|
||||
is_alias: false,
|
||||
});
|
||||
}
|
||||
|
||||
fn push_module(&mut self, module_id: ModuleId) {
|
||||
self.push_file_symbol(|s| {
|
||||
let def_map = module_id.def_map(s.db.upcast());
|
||||
let module_data = &def_map[module_id.local_id];
|
||||
let declaration = module_data.origin.declaration()?;
|
||||
let module = declaration.to_node(s.db.upcast());
|
||||
let name_node = module.name()?;
|
||||
Some(FileSymbol {
|
||||
name: name_node.text().into(),
|
||||
def: ModuleDef::Module(module_id.into()),
|
||||
container_name: s.current_container_name.clone(),
|
||||
loc: DeclarationLocation {
|
||||
hir_file_id: declaration.file_id,
|
||||
ptr: SyntaxNodePtr::new(module.syntax()),
|
||||
name_ptr: SyntaxNodePtr::new(name_node.syntax()),
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
let def_map = module_id.def_map(self.db.upcast());
|
||||
let module_data = &def_map[module_id.local_id];
|
||||
let Some(declaration) = module_data.origin.declaration() else { return };
|
||||
let module = declaration.to_node(self.db.upcast());
|
||||
let Some(name_node) = module.name() else { return };
|
||||
let dec_loc = DeclarationLocation {
|
||||
hir_file_id: declaration.file_id,
|
||||
ptr: SyntaxNodePtr::new(module.syntax()),
|
||||
name_ptr: SyntaxNodePtr::new(name_node.syntax()),
|
||||
};
|
||||
|
||||
fn push_file_symbol(&mut self, f: impl FnOnce(&Self) -> Option<FileSymbol>) {
|
||||
if let Some(file_symbol) = f(self) {
|
||||
self.symbols.push(file_symbol);
|
||||
let def = ModuleDef::Module(module_id.into());
|
||||
|
||||
if let Some(attrs) = def.attrs(self.db) {
|
||||
for alias in attrs.doc_aliases() {
|
||||
self.symbols.push(FileSymbol {
|
||||
name: alias,
|
||||
def,
|
||||
loc: dec_loc.clone(),
|
||||
container_name: self.current_container_name.clone(),
|
||||
is_alias: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
self.symbols.push(FileSymbol {
|
||||
name: name_node.text().into(),
|
||||
def: ModuleDef::Module(module_id.into()),
|
||||
container_name: self.current_container_name.clone(),
|
||||
loc: dec_loc,
|
||||
is_alias: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -434,4 +434,31 @@ mod a_mod {
|
||||
|
||||
expect_file!["./test_data/test_symbol_index_collection.txt"].assert_debug_eq(&symbols);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_doc_alias() {
|
||||
let (db, _) = RootDatabase::with_single_file(
|
||||
r#"
|
||||
#[doc(alias="s1")]
|
||||
#[doc(alias="s2")]
|
||||
#[doc(alias("mul1","mul2"))]
|
||||
struct Struct;
|
||||
|
||||
#[doc(alias="s1")]
|
||||
struct Duplicate;
|
||||
"#,
|
||||
);
|
||||
|
||||
let symbols: Vec<_> = Crate::from(db.test_crate())
|
||||
.modules(&db)
|
||||
.into_iter()
|
||||
.map(|module_id| {
|
||||
let mut symbols = SymbolCollector::collect_module(&db, module_id);
|
||||
symbols.sort_by_key(|it| it.name.clone());
|
||||
(module_id, symbols)
|
||||
})
|
||||
.collect();
|
||||
|
||||
expect_file!["./test_data/test_doc_alias.txt"].assert_debug_eq(&symbols);
|
||||
}
|
||||
}
|
||||
|
202
crates/ide-db/src/test_data/test_doc_alias.txt
Normal file
202
crates/ide-db/src/test_data/test_doc_alias.txt
Normal file
@ -0,0 +1,202 @@
|
||||
[
|
||||
(
|
||||
Module {
|
||||
id: ModuleId {
|
||||
krate: Idx::<CrateData>(0),
|
||||
block: None,
|
||||
local_id: Idx::<ModuleData>(0),
|
||||
},
|
||||
},
|
||||
[
|
||||
FileSymbol {
|
||||
name: "Duplicate",
|
||||
def: Adt(
|
||||
Struct(
|
||||
Struct {
|
||||
id: StructId(
|
||||
1,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: DeclarationLocation {
|
||||
hir_file_id: HirFileId(
|
||||
0,
|
||||
),
|
||||
ptr: SyntaxNodePtr {
|
||||
kind: STRUCT,
|
||||
range: 83..119,
|
||||
},
|
||||
name_ptr: SyntaxNodePtr {
|
||||
kind: NAME,
|
||||
range: 109..118,
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "Struct",
|
||||
def: Adt(
|
||||
Struct(
|
||||
Struct {
|
||||
id: StructId(
|
||||
0,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: DeclarationLocation {
|
||||
hir_file_id: HirFileId(
|
||||
0,
|
||||
),
|
||||
ptr: SyntaxNodePtr {
|
||||
kind: STRUCT,
|
||||
range: 0..81,
|
||||
},
|
||||
name_ptr: SyntaxNodePtr {
|
||||
kind: NAME,
|
||||
range: 74..80,
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "mul1",
|
||||
def: Adt(
|
||||
Struct(
|
||||
Struct {
|
||||
id: StructId(
|
||||
0,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: DeclarationLocation {
|
||||
hir_file_id: HirFileId(
|
||||
0,
|
||||
),
|
||||
ptr: SyntaxNodePtr {
|
||||
kind: STRUCT,
|
||||
range: 0..81,
|
||||
},
|
||||
name_ptr: SyntaxNodePtr {
|
||||
kind: NAME,
|
||||
range: 74..80,
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: true,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "mul2",
|
||||
def: Adt(
|
||||
Struct(
|
||||
Struct {
|
||||
id: StructId(
|
||||
0,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: DeclarationLocation {
|
||||
hir_file_id: HirFileId(
|
||||
0,
|
||||
),
|
||||
ptr: SyntaxNodePtr {
|
||||
kind: STRUCT,
|
||||
range: 0..81,
|
||||
},
|
||||
name_ptr: SyntaxNodePtr {
|
||||
kind: NAME,
|
||||
range: 74..80,
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: true,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "s1",
|
||||
def: Adt(
|
||||
Struct(
|
||||
Struct {
|
||||
id: StructId(
|
||||
0,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: DeclarationLocation {
|
||||
hir_file_id: HirFileId(
|
||||
0,
|
||||
),
|
||||
ptr: SyntaxNodePtr {
|
||||
kind: STRUCT,
|
||||
range: 0..81,
|
||||
},
|
||||
name_ptr: SyntaxNodePtr {
|
||||
kind: NAME,
|
||||
range: 74..80,
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: true,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "s1",
|
||||
def: Adt(
|
||||
Struct(
|
||||
Struct {
|
||||
id: StructId(
|
||||
1,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: DeclarationLocation {
|
||||
hir_file_id: HirFileId(
|
||||
0,
|
||||
),
|
||||
ptr: SyntaxNodePtr {
|
||||
kind: STRUCT,
|
||||
range: 83..119,
|
||||
},
|
||||
name_ptr: SyntaxNodePtr {
|
||||
kind: NAME,
|
||||
range: 109..118,
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: true,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "s2",
|
||||
def: Adt(
|
||||
Struct(
|
||||
Struct {
|
||||
id: StructId(
|
||||
0,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: DeclarationLocation {
|
||||
hir_file_id: HirFileId(
|
||||
0,
|
||||
),
|
||||
ptr: SyntaxNodePtr {
|
||||
kind: STRUCT,
|
||||
range: 0..81,
|
||||
},
|
||||
name_ptr: SyntaxNodePtr {
|
||||
kind: NAME,
|
||||
range: 74..80,
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: true,
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
@ -31,6 +31,7 @@
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "CONST",
|
||||
@ -55,6 +56,7 @@
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "CONST_WITH_INNER",
|
||||
@ -79,6 +81,7 @@
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "Enum",
|
||||
@ -105,6 +108,7 @@
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "Macro",
|
||||
@ -131,6 +135,7 @@
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "STATIC",
|
||||
@ -155,6 +160,7 @@
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "Struct",
|
||||
@ -181,6 +187,7 @@
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "StructFromMacro",
|
||||
@ -207,6 +214,7 @@
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "StructInFn",
|
||||
@ -235,6 +243,7 @@
|
||||
container_name: Some(
|
||||
"main",
|
||||
),
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "StructInNamedConst",
|
||||
@ -263,6 +272,7 @@
|
||||
container_name: Some(
|
||||
"CONST_WITH_INNER",
|
||||
),
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "StructInUnnamedConst",
|
||||
@ -289,6 +299,7 @@
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "Trait",
|
||||
@ -313,6 +324,7 @@
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "Union",
|
||||
@ -339,6 +351,7 @@
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "a_mod",
|
||||
@ -365,6 +378,7 @@
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "b_mod",
|
||||
@ -391,6 +405,7 @@
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "define_struct",
|
||||
@ -417,6 +432,7 @@
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "impl_fn",
|
||||
@ -441,6 +457,7 @@
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "macro_rules_macro",
|
||||
@ -467,6 +484,7 @@
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "main",
|
||||
@ -491,6 +509,7 @@
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
FileSymbol {
|
||||
name: "trait_fn",
|
||||
@ -517,6 +536,7 @@
|
||||
container_name: Some(
|
||||
"Trait",
|
||||
),
|
||||
is_alias: false,
|
||||
},
|
||||
],
|
||||
),
|
||||
@ -554,6 +574,7 @@
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
],
|
||||
),
|
||||
@ -591,6 +612,7 @@
|
||||
},
|
||||
},
|
||||
container_name: None,
|
||||
is_alias: false,
|
||||
},
|
||||
],
|
||||
),
|
||||
|
@ -113,6 +113,7 @@ fn try_lookup_include_path(
|
||||
file_id,
|
||||
full_range: TextRange::new(0.into(), size),
|
||||
name: path.into(),
|
||||
alias: None,
|
||||
focus_range: None,
|
||||
kind: None,
|
||||
container_name: None,
|
||||
|
@ -405,7 +405,7 @@ pub fn symbol_search(&self, query: Query) -> Cancellable<Vec<NavigationTarget>>
|
||||
self.with_db(|db| {
|
||||
symbol_index::world_symbols(db, query)
|
||||
.into_iter() // xx: should we make this a par iter?
|
||||
.filter_map(|s| s.def.try_to_nav(db))
|
||||
.filter_map(|s| s.try_to_nav(db))
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
}
|
||||
|
@ -45,6 +45,9 @@ pub struct NavigationTarget {
|
||||
pub container_name: Option<SmolStr>,
|
||||
pub description: Option<String>,
|
||||
pub docs: Option<Documentation>,
|
||||
/// In addition to a `name` field, a `NavigationTarget` may also be aliased
|
||||
/// In such cases we want a `NavigationTarget` to be accessible by its alias
|
||||
pub alias: Option<SmolStr>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for NavigationTarget {
|
||||
@ -154,6 +157,7 @@ fn from_syntax(
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
alias: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -165,7 +169,8 @@ fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||
|
||||
Some(NavigationTarget {
|
||||
file_id: full_range.file_id,
|
||||
name: self.name.clone(),
|
||||
name: if self.is_alias { self.def.name(db)?.to_smol_str() } else { self.name.clone() },
|
||||
alias: if self.is_alias { Some(self.name.clone()) } else { None },
|
||||
kind: Some(hir::ModuleDefId::from(self.def).into()),
|
||||
full_range: full_range.range,
|
||||
focus_range: Some(name_range.range),
|
||||
@ -466,6 +471,7 @@ fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
|
||||
NavigationTarget {
|
||||
file_id,
|
||||
name,
|
||||
alias: None,
|
||||
kind: Some(kind),
|
||||
full_range,
|
||||
focus_range,
|
||||
@ -494,6 +500,7 @@ fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
|
||||
NavigationTarget {
|
||||
file_id,
|
||||
name,
|
||||
alias: None,
|
||||
kind: Some(SymbolKind::Label),
|
||||
full_range,
|
||||
focus_range,
|
||||
@ -534,6 +541,7 @@ fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||
Some(NavigationTarget {
|
||||
file_id,
|
||||
name,
|
||||
alias: None,
|
||||
kind: Some(SymbolKind::TypeParam),
|
||||
full_range,
|
||||
focus_range,
|
||||
@ -560,6 +568,7 @@ fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||
Some(NavigationTarget {
|
||||
file_id,
|
||||
name,
|
||||
alias: None,
|
||||
kind: Some(SymbolKind::LifetimeParam),
|
||||
full_range,
|
||||
focus_range: Some(full_range),
|
||||
@ -589,6 +598,7 @@ fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||
Some(NavigationTarget {
|
||||
file_id,
|
||||
name,
|
||||
alias: None,
|
||||
kind: Some(SymbolKind::ConstParam),
|
||||
full_range,
|
||||
focus_range,
|
||||
@ -643,6 +653,7 @@ fn foo() { enum FooInner { } }
|
||||
focus_range: 34..42,
|
||||
name: "FooInner",
|
||||
kind: Enum,
|
||||
container_name: "foo",
|
||||
description: "enum FooInner",
|
||||
},
|
||||
]
|
||||
|
@ -2242,14 +2242,14 @@ fn foo2_test() {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 52..115,
|
||||
focus_range: 67..75,
|
||||
name: "foo_test",
|
||||
full_range: 121..185,
|
||||
focus_range: 136..145,
|
||||
name: "foo2_test",
|
||||
kind: Function,
|
||||
},
|
||||
kind: Test {
|
||||
test_id: Path(
|
||||
"tests::foo_test",
|
||||
"tests::foo2_test",
|
||||
),
|
||||
attr: TestAttr {
|
||||
ignore: false,
|
||||
@ -2263,14 +2263,14 @@ fn foo2_test() {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 121..185,
|
||||
focus_range: 136..145,
|
||||
name: "foo2_test",
|
||||
full_range: 52..115,
|
||||
focus_range: 67..75,
|
||||
name: "foo_test",
|
||||
kind: Function,
|
||||
},
|
||||
kind: Test {
|
||||
test_id: Path(
|
||||
"tests::foo2_test",
|
||||
"tests::foo_test",
|
||||
),
|
||||
attr: TestAttr {
|
||||
ignore: false,
|
||||
|
@ -520,7 +520,10 @@ fn exec_query(snap: &GlobalStateSnapshot, query: Query) -> Result<Vec<SymbolInfo
|
||||
|
||||
#[allow(deprecated)]
|
||||
let info = SymbolInformation {
|
||||
name: nav.name.to_string(),
|
||||
name: match &nav.alias {
|
||||
Some(alias) => format!("{} (alias for {})", alias, nav.name),
|
||||
None => format!("{}", nav.name),
|
||||
},
|
||||
kind: nav
|
||||
.kind
|
||||
.map(to_proto::symbol_kind)
|
||||
|
Loading…
Reference in New Issue
Block a user