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:
bors 2023-05-26 11:30:40 +00:00
commit 8589a2d843
9 changed files with 337 additions and 47 deletions

View File

@ -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,
});
}
}

View File

@ -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);
}
}

View 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,
},
],
),
]

View File

@ -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,
},
],
),

View File

@ -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,

View File

@ -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<_>>()
})
}

View File

@ -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",
},
]

View File

@ -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,

View File

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