assert!(meta.path.starts_with(&source_root_prefix));
if let Some(krate) = meta.krate {
+ let crate_name = CrateName::normalize_dashes(&krate);
let crate_id = crate_graph.add_crate_root(
file_id,
meta.edition,
- Some(krate.clone()),
+ Some(crate_name.clone()),
meta.cfg,
meta.env,
Default::default(),
);
- let crate_name = CrateName::new(&krate).unwrap();
let prev = crates.insert(crate_name.clone(), crate_id);
assert!(prev.is_none());
for dep in meta.deps {
- let dep = CrateName::new(&dep).unwrap();
+ let dep = CrateName::normalize_dashes(&dep);
crate_deps.push((crate_name.clone(), dep))
}
} else if meta.path == "/main.rs" || meta.path == "/lib.rs" {
crate_graph.add_crate_root(
crate_root,
Edition::Edition2018,
- Some("test".to_string()),
+ Some(CrateName::new("test").unwrap()),
default_cfg,
Env::default(),
Default::default(),
pub struct CrateData {
pub root_file_id: FileId,
pub edition: Edition,
- /// The name to display to the end user.
- /// This actual crate name can be different in a particular dependent crate
- /// or may even be missing for some cases, such as a dummy crate for the code snippet.
- pub display_name: Option<String>,
+ /// A name used in the package's project declaration: for Cargo projects, it's [package].name,
+ /// can be different for other project types or even absent (a dummy crate for the code snippet, for example).
+ /// NOTE: The crate can be referenced as a dependency under a different name,
+ /// this one should be used when working with crate hierarchies.
+ pub declaration_name: Option<CrateName>,
pub cfg_options: CfgOptions,
pub env: Env,
pub dependencies: Vec<Dependency>,
&mut self,
file_id: FileId,
edition: Edition,
- display_name: Option<String>,
+ declaration_name: Option<CrateName>,
cfg_options: CfgOptions,
env: Env,
proc_macro: Vec<(SmolStr, Arc<dyn tt::TokenExpander>)>,
let data = CrateData {
root_file_id: file_id,
edition,
- display_name,
+ declaration_name,
cfg_options,
env,
proc_macro,
use std::{iter, sync::Arc};
use arrayvec::ArrayVec;
-use base_db::{CrateId, Edition, FileId};
+use base_db::{CrateId, CrateName, Edition, FileId};
use either::Either;
use hir_def::find_path::PrefixKind;
use hir_def::{
db.crate_graph()[self.id].edition
}
- pub fn display_name(self, db: &dyn HirDatabase) -> Option<String> {
- db.crate_graph()[self.id].display_name.clone()
+ pub fn declaration_name(self, db: &dyn HirDatabase) -> Option<CrateName> {
+ db.crate_graph()[self.id].declaration_name.clone()
}
pub fn query_external_importables(
use super::*;
- fn check_search(ra_fixture: &str, krate_name: &str, query: Query, expect: Expect) {
+ fn check_search(ra_fixture: &str, crate_name: &str, query: Query, expect: Expect) {
let db = TestDB::with_files(ra_fixture);
let crate_graph = db.crate_graph();
let krate = crate_graph
.iter()
.find(|krate| {
- crate_graph[*krate].display_name.as_ref().map(|n| n.to_string())
- == Some(krate_name.to_string())
+ crate_graph[*krate].declaration_name.as_ref().map(|n| n.to_string())
+ == Some(crate_name.to_string())
})
.unwrap();
let path = map.path_of(item).unwrap();
format!(
"{}::{} ({})\n",
- crate_graph[krate].display_name.as_ref().unwrap(),
+ crate_graph[krate].declaration_name.as_ref().unwrap(),
path,
mark
)
.iter()
.filter_map(|krate| {
let cdata = &crate_graph[krate];
- let name = cdata.display_name.as_ref()?;
+ let name = cdata.declaration_name.as_ref()?;
let map = db.import_map(krate);
pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<CrateDefMap> {
let _p = profile::span("crate_def_map_query").detail(|| {
db.crate_graph()[krate]
- .display_name
+ .declaration_name
.as_ref()
.map(ToString::to_string)
.unwrap_or_default()
fn render_path(db: &RootDatabase, module: Module, item_name: Option<String>) -> String {
let crate_name =
- db.crate_graph()[module.krate().into()].display_name.as_ref().map(ToString::to_string);
+ db.crate_graph()[module.krate().into()].declaration_name.as_ref().map(ToString::to_string);
let module_path = module
.path_to_root(db)
.into_iter()
"#]],
);
}
+
+ #[test]
+ fn hover_displays_normalized_crate_names() {
+ check(
+ r#"
+//- /lib.rs crate:name-with-dashes
+pub mod wrapper {
+ pub struct Thing { x: u32 }
+
+ impl Thing {
+ pub fn new() -> Thing { Thing { x: 0 } }
+ }
+}
+
+//- /main.rs crate:main deps:name-with-dashes
+fn main() { let foo_test = name_with_dashes::wrapper::Thing::new<|>(); }
+"#,
+ expect![[r#"
+ *new*
+
+ ```rust
+ name_with_dashes::wrapper::Thing
+ ```
+
+ ```rust
+ pub fn new() -> Thing
+ ```
+ "#]],
+ )
+ }
}
let krate = resolved.module(db)?.krate();
let canonical_path = resolved.canonical_path(db)?;
let new_target = get_doc_url(db, &krate)?
- .join(&format!("{}/", krate.display_name(db)?))
+ .join(&format!("{}/", krate.declaration_name(db)?))
.ok()?
.join(&canonical_path.replace("::", "/"))
.ok()?
let module = def.module(db)?;
let krate = module.krate();
let canonical_path = def.canonical_path(db)?;
- let base = format!("{}/{}", krate.display_name(db)?, canonical_path.replace("::", "/"));
+ let base = format!("{}/{}", krate.declaration_name(db)?, canonical_path.replace("::", "/"));
get_doc_url(db, &krate)
.and_then(|url| url.join(&base).ok())
//
// FIXME: clicking on the link should just open the file in the editor,
// instead of falling back to external urls.
- Some(format!("https://docs.rs/{}/*/", krate.display_name(db)?))
+ Some(format!("https://docs.rs/{}/*/", krate.declaration_name(db)?))
})
.and_then(|s| Url::parse(&s).ok())
}
match krate {
Some(krate) => {
let crate_graph = db.crate_graph();
- let display_crate = |krate: CrateId| match &crate_graph[krate].display_name {
+ let display_crate = |krate: CrateId| match &crate_graph[krate].declaration_name {
Some(it) => format!("{}({:?})", it, krate),
None => format!("{:?}", krate),
};
let crate_id = crate_graph.add_crate_root(
file_id,
edition,
- Some(cargo[pkg].name.clone()),
+ Some(CrateName::normalize_dashes(&cargo[pkg].name)),
cfg_options,
env,
proc_macro.clone(),
let env = Env::default();
let proc_macro = vec![];
- let name = sysroot[krate].name.clone();
+ let name = CrateName::new(&sysroot[krate].name)
+ .expect("Sysroot crates' names do not contain dashes");
let crate_id = crate_graph.add_crate_root(
file_id,
Edition::Edition2018,
for module in work {
let file_id = module.definition_source(db).file_id.original_file(db);
if !visited_files.contains(&file_id) {
- let crate_name = if let Some(name) = module.krate().display_name(db) {
- format!("{}", name)
- } else {
- String::from("unknown")
- };
+ let crate_name = module
+ .krate()
+ .declaration_name(db)
+ .as_ref()
+ .map(ToString::to_string)
+ .unwrap_or_else(|| "unknown".to_string());
println!("processing crate: {}, module: {}", crate_name, _vfs.file_path(file_id));
for diagnostic in analysis.diagnostics(&DiagnosticsConfig::default(), file_id).unwrap()
{