Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir/src/symbols.rs98
-rw-r--r--crates/ide-db/src/symbol_index.rs27
-rw-r--r--crates/ide-db/src/test_data/test_doc_alias.txt202
-rw-r--r--crates/ide-db/src/test_data/test_symbol_index_collection.txt22
-rw-r--r--crates/ide/src/goto_definition.rs1
-rw-r--r--crates/ide/src/lib.rs2
-rw-r--r--crates/ide/src/navigation_target.rs13
-rw-r--r--crates/ide/src/runnables.rs16
-rw-r--r--crates/rust-analyzer/src/handlers/request.rs5
9 files changed, 338 insertions, 48 deletions
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index af37206ead..207e8206c9 100644
--- a/crates/hir/src/symbols.rs
+++ b/crates/hir/src/symbols.rs
@@ -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 @@ impl<'a> SymbolCollector<'a> {
<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,
+ });
+ }
+ }
- 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()),
- },
- })
- })
+ 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_file_symbol(&mut self, f: impl FnOnce(&Self) -> Option<FileSymbol>) {
- if let Some(file_symbol) = f(self) {
- self.symbols.push(file_symbol);
+ fn push_module(&mut self, module_id: ModuleId) {
+ 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()),
+ };
+
+ 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,
+ });
}
}
diff --git a/crates/ide-db/src/symbol_index.rs b/crates/ide-db/src/symbol_index.rs
index fa796ae13b..b54c43b296 100644
--- a/crates/ide-db/src/symbol_index.rs
+++ b/crates/ide-db/src/symbol_index.rs
@@ -434,4 +434,31 @@ struct StructInModB;
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);
+ }
}
diff --git a/crates/ide-db/src/test_data/test_doc_alias.txt b/crates/ide-db/src/test_data/test_doc_alias.txt
new file mode 100644
index 0000000000..77714efa35
--- /dev/null
+++ b/crates/ide-db/src/test_data/test_doc_alias.txt
@@ -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,
+ },
+ ],
+ ),
+]
diff --git a/crates/ide-db/src/test_data/test_symbol_index_collection.txt b/crates/ide-db/src/test_data/test_symbol_index_collection.txt
index 1e34dd633c..b5adfc13d9 100644
--- a/crates/ide-db/src/test_data/test_symbol_index_collection.txt
+++ b/crates/ide-db/src/test_data/test_symbol_index_collection.txt
@@ -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,
},
],
),
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index ef3f14d79d..4e641357e3 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -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,
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 72d20af663..4e5f01e716 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -405,7 +405,7 @@ impl Analysis {
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<_>>()
})
}
diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs
index d8ce79de37..65c37ca68c 100644
--- a/crates/ide/src/navigation_target.rs
+++ b/crates/ide/src/navigation_target.rs
@@ -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 @@ impl NavigationTarget {
container_name: None,
description: None,
docs: None,
+ alias: None,
}
}
}
@@ -165,7 +169,8 @@ impl TryToNav for FileSymbol {
Some(NavigationTarget {
file_id: full_range.file_id,
- name: self.name.clone(),
+ name: self.def.name(db)?.to_smol_str(),
+ 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 @@ impl ToNav for LocalSource {
NavigationTarget {
file_id,
name,
+ alias: None,
kind: Some(kind),
full_range,
focus_range,
@@ -494,6 +500,7 @@ impl ToNav for hir::Label {
NavigationTarget {
file_id,
name,
+ alias: None,
kind: Some(SymbolKind::Label),
full_range,
focus_range,
@@ -534,6 +541,7 @@ impl TryToNav for hir::TypeParam {
Some(NavigationTarget {
file_id,
name,
+ alias: None,
kind: Some(SymbolKind::TypeParam),
full_range,
focus_range,
@@ -560,6 +568,7 @@ impl TryToNav for hir::LifetimeParam {
Some(NavigationTarget {
file_id,
name,
+ alias: None,
kind: Some(SymbolKind::LifetimeParam),
full_range,
focus_range: Some(full_range),
@@ -589,6 +598,7 @@ impl TryToNav for hir::ConstParam {
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",
},
]
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index 64150cc2f7..ec57c02145 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -2232,14 +2232,14 @@ mod tests {
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,
@@ -2253,14 +2253,14 @@ mod tests {
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,
diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs
index 9c198eefc7..c8eda567db 100644
--- a/crates/rust-analyzer/src/handlers/request.rs
+++ b/crates/rust-analyzer/src/handlers/request.rs
@@ -520,7 +520,10 @@ pub(crate) fn handle_workspace_symbol(
#[allow(deprecated)]
let info = SymbolInformation {
- name: nav.name.to_string(),
+ name: match nav.alias {
+ Some(ref alias) => format!("{} (alias {})", alias, nav.name),
+ None => format!("{}", nav.name),
+ },
kind: nav
.kind
.map(to_proto::symbol_kind)