mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-26 11:59:49 +00:00
Add ExternCrateDecl to HIR
This commit is contained in:
parent
151c750dac
commit
bcff166b3a
39 changed files with 585 additions and 167 deletions
|
@ -14,8 +14,8 @@ use crate::{
|
||||||
item_scope::ItemScope,
|
item_scope::ItemScope,
|
||||||
nameres::DefMap,
|
nameres::DefMap,
|
||||||
src::{HasChildSource, HasSource},
|
src::{HasChildSource, HasSource},
|
||||||
AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, FieldId, ImplId, Lookup, MacroId,
|
AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FieldId, ImplId,
|
||||||
ModuleDefId, ModuleId, TraitId, VariantId,
|
Lookup, MacroId, ModuleDefId, ModuleId, TraitId, VariantId,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait ChildBySource {
|
pub trait ChildBySource {
|
||||||
|
@ -91,6 +91,7 @@ impl ChildBySource for ItemScope {
|
||||||
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
|
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
|
||||||
self.declarations().for_each(|item| add_module_def(db, res, file_id, item));
|
self.declarations().for_each(|item| add_module_def(db, res, file_id, item));
|
||||||
self.impls().for_each(|imp| add_impl(db, res, file_id, imp));
|
self.impls().for_each(|imp| add_impl(db, res, file_id, imp));
|
||||||
|
self.extern_crate_decls().for_each(|ext| add_extern_crate(db, res, file_id, ext));
|
||||||
self.unnamed_consts().for_each(|konst| {
|
self.unnamed_consts().for_each(|konst| {
|
||||||
let loc = konst.lookup(db);
|
let loc = konst.lookup(db);
|
||||||
if loc.id.file_id() == file_id {
|
if loc.id.file_id() == file_id {
|
||||||
|
@ -167,6 +168,17 @@ impl ChildBySource for ItemScope {
|
||||||
map[keys::IMPL].insert(loc.source(db).value, imp)
|
map[keys::IMPL].insert(loc.source(db).value, imp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn add_extern_crate(
|
||||||
|
db: &dyn DefDatabase,
|
||||||
|
map: &mut DynMap,
|
||||||
|
file_id: HirFileId,
|
||||||
|
ext: ExternCrateId,
|
||||||
|
) {
|
||||||
|
let loc = ext.lookup(db);
|
||||||
|
if loc.id.file_id() == file_id {
|
||||||
|
map[keys::EXTERN_CRATE].insert(loc.source(db).value, ext)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
pub mod adt;
|
pub mod adt;
|
||||||
|
|
||||||
|
use base_db::CrateId;
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind,
|
name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind,
|
||||||
};
|
};
|
||||||
|
@ -467,6 +468,7 @@ pub struct ExternCrateDeclData {
|
||||||
pub name: Name,
|
pub name: Name,
|
||||||
pub alias: Option<ImportAlias>,
|
pub alias: Option<ImportAlias>,
|
||||||
pub visibility: RawVisibility,
|
pub visibility: RawVisibility,
|
||||||
|
pub crate_id: CrateId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExternCrateDeclData {
|
impl ExternCrateDeclData {
|
||||||
|
@ -478,10 +480,24 @@ impl ExternCrateDeclData {
|
||||||
let item_tree = loc.id.item_tree(db);
|
let item_tree = loc.id.item_tree(db);
|
||||||
let extern_crate = &item_tree[loc.id.value];
|
let extern_crate = &item_tree[loc.id.value];
|
||||||
|
|
||||||
|
let name = extern_crate.name.clone();
|
||||||
|
let crate_id = if name == hir_expand::name![self] {
|
||||||
|
loc.container.krate()
|
||||||
|
} else {
|
||||||
|
db.crate_def_map(loc.container.krate())
|
||||||
|
.extern_prelude()
|
||||||
|
.find(|&(prelude_name, ..)| *prelude_name == name)
|
||||||
|
// FIXME: Suspicious unwrap
|
||||||
|
.unwrap()
|
||||||
|
.1
|
||||||
|
.krate()
|
||||||
|
};
|
||||||
|
|
||||||
Arc::new(Self {
|
Arc::new(Self {
|
||||||
name: extern_crate.name.clone(),
|
name: extern_crate.name.clone(),
|
||||||
visibility: item_tree[extern_crate.visibility].clone(),
|
visibility: item_tree[extern_crate.visibility].clone(),
|
||||||
alias: extern_crate.alias.clone(),
|
alias: extern_crate.alias.clone(),
|
||||||
|
crate_id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,6 +113,12 @@ impl ItemScope {
|
||||||
self.declarations.iter().copied()
|
self.declarations.iter().copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn extern_crate_decls(
|
||||||
|
&self,
|
||||||
|
) -> impl Iterator<Item = ExternCrateId> + ExactSizeIterator + '_ {
|
||||||
|
self.extern_crate_decls.iter().copied()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn impls(&self) -> impl Iterator<Item = ImplId> + ExactSizeIterator + '_ {
|
pub fn impls(&self) -> impl Iterator<Item = ImplId> + ExactSizeIterator + '_ {
|
||||||
self.impls.iter().copied()
|
self.impls.iter().copied()
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,6 +121,12 @@ impl From<CrateRootModuleId> for ModuleDefId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<CrateId> for CrateRootModuleId {
|
||||||
|
fn from(krate: CrateId) -> Self {
|
||||||
|
CrateRootModuleId { krate }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TryFrom<ModuleId> for CrateRootModuleId {
|
impl TryFrom<ModuleId> for CrateRootModuleId {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
|
|
||||||
|
|
|
@ -213,17 +213,17 @@ pub type Ty = ();
|
||||||
|
|
||||||
for (_, res) in module_data.scope.resolutions() {
|
for (_, res) in module_data.scope.resolutions() {
|
||||||
match res.values.or(res.types).unwrap().0 {
|
match res.values.or(res.types).unwrap().0 {
|
||||||
ModuleDefId::FunctionId(f) => drop(db.function_data(f)),
|
ModuleDefId::FunctionId(f) => _ = db.function_data(f),
|
||||||
ModuleDefId::AdtId(adt) => match adt {
|
ModuleDefId::AdtId(adt) => match adt {
|
||||||
AdtId::StructId(it) => drop(db.struct_data(it)),
|
AdtId::StructId(it) => _ = db.struct_data(it),
|
||||||
AdtId::UnionId(it) => drop(db.union_data(it)),
|
AdtId::UnionId(it) => _ = db.union_data(it),
|
||||||
AdtId::EnumId(it) => drop(db.enum_data(it)),
|
AdtId::EnumId(it) => _ = db.enum_data(it),
|
||||||
},
|
},
|
||||||
ModuleDefId::ConstId(it) => drop(db.const_data(it)),
|
ModuleDefId::ConstId(it) => _ = db.const_data(it),
|
||||||
ModuleDefId::StaticId(it) => drop(db.static_data(it)),
|
ModuleDefId::StaticId(it) => _ = db.static_data(it),
|
||||||
ModuleDefId::TraitId(it) => drop(db.trait_data(it)),
|
ModuleDefId::TraitId(it) => _ = db.trait_data(it),
|
||||||
ModuleDefId::TraitAliasId(it) => drop(db.trait_alias_data(it)),
|
ModuleDefId::TraitAliasId(it) => _ = db.trait_alias_data(it),
|
||||||
ModuleDefId::TypeAliasId(it) => drop(db.type_alias_data(it)),
|
ModuleDefId::TypeAliasId(it) => _ = db.type_alias_data(it),
|
||||||
ModuleDefId::EnumVariantId(_)
|
ModuleDefId::EnumVariantId(_)
|
||||||
| ModuleDefId::ModuleId(_)
|
| ModuleDefId::ModuleId(_)
|
||||||
| ModuleDefId::MacroId(_)
|
| ModuleDefId::MacroId(_)
|
||||||
|
|
|
@ -12,9 +12,9 @@ use hir_ty::db::HirDatabase;
|
||||||
use syntax::{ast, AstNode};
|
use syntax::{ast, AstNode};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Adt, AssocItem, Const, ConstParam, Enum, Field, Function, GenericParam, Impl, LifetimeParam,
|
Adt, AssocItem, Const, ConstParam, Enum, ExternCrateDecl, Field, Function, GenericParam, Impl,
|
||||||
Macro, Module, ModuleDef, Static, Struct, Trait, TraitAlias, TypeAlias, TypeParam, Union,
|
LifetimeParam, Macro, Module, ModuleDef, Static, Struct, Trait, TraitAlias, TypeAlias,
|
||||||
Variant,
|
TypeParam, Union, Variant,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait HasAttrs {
|
pub trait HasAttrs {
|
||||||
|
@ -120,6 +120,39 @@ impl HasAttrs for AssocItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl HasAttrs for ExternCrateDecl {
|
||||||
|
fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner {
|
||||||
|
let def = AttrDefId::ExternCrateId(self.into());
|
||||||
|
db.attrs_with_owner(def)
|
||||||
|
}
|
||||||
|
fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> {
|
||||||
|
let crate_docs = self.resolved_crate(db).root_module().attrs(db).docs().map(String::from);
|
||||||
|
let def = AttrDefId::ExternCrateId(self.into());
|
||||||
|
let decl_docs = db.attrs(def).docs().map(String::from);
|
||||||
|
match (decl_docs, crate_docs) {
|
||||||
|
(None, None) => None,
|
||||||
|
(Some(decl_docs), None) => Some(decl_docs),
|
||||||
|
(None, Some(crate_docs)) => Some(crate_docs),
|
||||||
|
(Some(mut decl_docs), Some(crate_docs)) => {
|
||||||
|
decl_docs.push('\n');
|
||||||
|
decl_docs.push('\n');
|
||||||
|
decl_docs += &crate_docs;
|
||||||
|
Some(decl_docs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.map(Documentation::new)
|
||||||
|
}
|
||||||
|
fn resolve_doc_path(
|
||||||
|
self,
|
||||||
|
db: &dyn HirDatabase,
|
||||||
|
link: &str,
|
||||||
|
ns: Option<Namespace>,
|
||||||
|
) -> Option<ModuleDef> {
|
||||||
|
let def = AttrDefId::ExternCrateId(self.into());
|
||||||
|
resolve_doc_path(db, def, link, ns).map(ModuleDef::from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Resolves the item `link` points to in the scope of `def`.
|
/// Resolves the item `link` points to in the scope of `def`.
|
||||||
fn resolve_doc_path(
|
fn resolve_doc_path(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
|
|
|
@ -10,8 +10,3 @@ pub use hir_expand::db::{
|
||||||
MacroExpandQuery, ParseMacroExpansionErrorQuery, ParseMacroExpansionQuery,
|
MacroExpandQuery, ParseMacroExpansionErrorQuery, ParseMacroExpansionQuery,
|
||||||
};
|
};
|
||||||
pub use hir_ty::db::*;
|
pub use hir_ty::db::*;
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn hir_database_is_object_safe() {
|
|
||||||
fn _assert_object_safe(_: &dyn HirDatabase) {}
|
|
||||||
}
|
|
||||||
|
|
|
@ -18,9 +18,9 @@ use hir_ty::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Enum, Field, Function, GenericParam,
|
Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field,
|
||||||
HasCrate, HasVisibility, LifetimeParam, Macro, Module, Static, Struct, Trait, TraitAlias,
|
Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, Static, Struct,
|
||||||
TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam, Union, Variant,
|
Trait, TraitAlias, TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam, Union, Variant,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl HirDisplay for Function {
|
impl HirDisplay for Function {
|
||||||
|
@ -238,6 +238,18 @@ impl HirDisplay for Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl HirDisplay for ExternCrateDecl {
|
||||||
|
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||||
|
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
|
||||||
|
f.write_str("extern crate ")?;
|
||||||
|
write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
|
||||||
|
if let Some(alias) = self.alias(f.db) {
|
||||||
|
write!(f, " as {alias}",)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl HirDisplay for GenericParam {
|
impl HirDisplay for GenericParam {
|
||||||
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -15,7 +15,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
macro_rules! from_id {
|
macro_rules! from_id {
|
||||||
($(($id:path, $ty:path)),*) => {$(
|
($(($id:path, $ty:path)),* $(,)?) => {$(
|
||||||
impl From<$id> for $ty {
|
impl From<$id> for $ty {
|
||||||
fn from(id: $id) -> $ty {
|
fn from(id: $id) -> $ty {
|
||||||
$ty { id }
|
$ty { id }
|
||||||
|
@ -47,7 +47,8 @@ from_id![
|
||||||
(hir_def::TypeParamId, crate::TypeParam),
|
(hir_def::TypeParamId, crate::TypeParam),
|
||||||
(hir_def::ConstParamId, crate::ConstParam),
|
(hir_def::ConstParamId, crate::ConstParam),
|
||||||
(hir_def::LifetimeParamId, crate::LifetimeParam),
|
(hir_def::LifetimeParamId, crate::LifetimeParam),
|
||||||
(hir_def::MacroId, crate::Macro)
|
(hir_def::MacroId, crate::Macro),
|
||||||
|
(hir_def::ExternCrateId, crate::ExternCrateDecl),
|
||||||
];
|
];
|
||||||
|
|
||||||
impl From<AdtId> for Adt {
|
impl From<AdtId> for Adt {
|
||||||
|
|
|
@ -11,9 +11,9 @@ use hir_expand::{HirFileId, InFile};
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase, Adt, Const, Enum, Field, FieldSource, Function, Impl, LifetimeParam,
|
db::HirDatabase, Adt, Const, Enum, ExternCrateDecl, Field, FieldSource, Function, Impl,
|
||||||
LocalSource, Macro, Module, Static, Struct, Trait, TraitAlias, TypeAlias, TypeOrConstParam,
|
LifetimeParam, LocalSource, Macro, Module, Static, Struct, Trait, TraitAlias, TypeAlias,
|
||||||
Union, Variant,
|
TypeOrConstParam, Union, Variant,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait HasSource {
|
pub trait HasSource {
|
||||||
|
@ -207,3 +207,11 @@ impl HasSource for LocalSource {
|
||||||
Some(self.source)
|
Some(self.source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl HasSource for ExternCrateDecl {
|
||||||
|
type Ast = ast::ExternCrate;
|
||||||
|
|
||||||
|
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
|
||||||
|
Some(self.id.lookup(db.upcast()).source(db.upcast()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -48,14 +48,15 @@ use hir_def::{
|
||||||
layout::{self, ReprOptions, TargetDataLayout},
|
layout::{self, ReprOptions, TargetDataLayout},
|
||||||
macro_id_to_def_id,
|
macro_id_to_def_id,
|
||||||
nameres::{self, diagnostics::DefDiagnostic},
|
nameres::{self, diagnostics::DefDiagnostic},
|
||||||
|
path::ImportAlias,
|
||||||
per_ns::PerNs,
|
per_ns::PerNs,
|
||||||
resolver::{HasResolver, Resolver},
|
resolver::{HasResolver, Resolver},
|
||||||
src::HasSource as _,
|
src::HasSource as _,
|
||||||
AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId,
|
AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId,
|
||||||
EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, InTypeConstId, ItemContainerId,
|
EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, HasModule, ImplId,
|
||||||
LifetimeParamId, LocalEnumVariantId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId,
|
InTypeConstId, ItemContainerId, LifetimeParamId, LocalEnumVariantId, LocalFieldId, Lookup,
|
||||||
StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId,
|
MacroExpander, MacroId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId,
|
||||||
UnionId,
|
TypeOrConstParamId, TypeParamId, UnionId,
|
||||||
};
|
};
|
||||||
use hir_expand::{name::name, MacroCallKind};
|
use hir_expand::{name::name, MacroCallKind};
|
||||||
use hir_ty::{
|
use hir_ty::{
|
||||||
|
@ -200,9 +201,8 @@ impl Crate {
|
||||||
db.crate_graph().transitive_rev_deps(self.id).map(|id| Crate { id })
|
db.crate_graph().transitive_rev_deps(self.id).map(|id| Crate { id })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn root_module(self, db: &dyn HirDatabase) -> Module {
|
pub fn root_module(self) -> Module {
|
||||||
let def_map = db.crate_def_map(self.id);
|
Module { id: CrateRootModuleId::from(self.id).into() }
|
||||||
Module { id: def_map.crate_root().into() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn modules(self, db: &dyn HirDatabase) -> Vec<Module> {
|
pub fn modules(self, db: &dyn HirDatabase) -> Vec<Module> {
|
||||||
|
@ -247,7 +247,7 @@ impl Crate {
|
||||||
/// Try to get the root URL of the documentation of a crate.
|
/// Try to get the root URL of the documentation of a crate.
|
||||||
pub fn get_html_root_url(self: &Crate, db: &dyn HirDatabase) -> Option<String> {
|
pub fn get_html_root_url(self: &Crate, db: &dyn HirDatabase) -> Option<String> {
|
||||||
// Look for #![doc(html_root_url = "...")]
|
// Look for #![doc(html_root_url = "...")]
|
||||||
let attrs = db.attrs(AttrDefId::ModuleId(self.root_module(db).into()));
|
let attrs = db.attrs(AttrDefId::ModuleId(self.root_module().into()));
|
||||||
let doc_url = attrs.by_key("doc").find_string_value_in_tt("html_root_url");
|
let doc_url = attrs.by_key("doc").find_string_value_in_tt("html_root_url");
|
||||||
doc_url.map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/")
|
doc_url.map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/")
|
||||||
}
|
}
|
||||||
|
@ -2128,6 +2128,47 @@ impl HasVisibility for Function {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub struct ExternCrateDecl {
|
||||||
|
pub(crate) id: ExternCrateId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExternCrateDecl {
|
||||||
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
||||||
|
self.id.module(db.upcast()).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolved_crate(self, db: &dyn HirDatabase) -> Crate {
|
||||||
|
db.extern_crate_decl_data(self.id).crate_id.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
||||||
|
db.extern_crate_decl_data(self.id).name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn alias(self, db: &dyn HirDatabase) -> Option<ImportAlias> {
|
||||||
|
db.extern_crate_decl_data(self.id).alias.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the name under which this crate is made accessible, taking `_` into account.
|
||||||
|
pub fn alias_or_name(self, db: &dyn HirDatabase) -> Option<Name> {
|
||||||
|
let extern_crate_decl_data = db.extern_crate_decl_data(self.id);
|
||||||
|
match &extern_crate_decl_data.alias {
|
||||||
|
Some(ImportAlias::Underscore) => None,
|
||||||
|
Some(ImportAlias::Alias(alias)) => Some(alias.clone()),
|
||||||
|
None => Some(extern_crate_decl_data.name.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HasVisibility for ExternCrateDecl {
|
||||||
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
||||||
|
db.extern_crate_decl_data(self.id)
|
||||||
|
.visibility
|
||||||
|
.resolve(db.upcast(), &self.id.resolver(db.upcast()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct InTypeConst {
|
pub struct InTypeConst {
|
||||||
pub(crate) id: InTypeConstId,
|
pub(crate) id: InTypeConstId,
|
||||||
|
@ -4715,6 +4756,12 @@ pub trait HasContainer {
|
||||||
fn container(&self, db: &dyn HirDatabase) -> ItemContainer;
|
fn container(&self, db: &dyn HirDatabase) -> ItemContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl HasContainer for ExternCrateDecl {
|
||||||
|
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
|
||||||
|
container_id_to_hir(self.id.lookup(db.upcast()).container.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl HasContainer for Module {
|
impl HasContainer for Module {
|
||||||
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
|
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
|
||||||
// FIXME: handle block expressions as modules (their parent is in a different DefMap)
|
// FIXME: handle block expressions as modules (their parent is in a different DefMap)
|
||||||
|
|
|
@ -15,11 +15,7 @@ use hir_def::{
|
||||||
type_ref::Mutability,
|
type_ref::Mutability,
|
||||||
AsMacroCall, DefWithBodyId, FieldId, FunctionId, MacroId, TraitId, VariantId,
|
AsMacroCall, DefWithBodyId, FieldId, FunctionId, MacroId, TraitId, VariantId,
|
||||||
};
|
};
|
||||||
use hir_expand::{
|
use hir_expand::{db::ExpandDatabase, name::AsName, ExpansionInfo, MacroCallId};
|
||||||
db::ExpandDatabase,
|
|
||||||
name::{known, AsName},
|
|
||||||
ExpansionInfo, MacroCallId,
|
|
||||||
};
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
@ -439,10 +435,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
|
||||||
self.imp.resolve_path(path)
|
self.imp.resolve_path(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option<Crate> {
|
|
||||||
self.imp.resolve_extern_crate(extern_crate)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantDef> {
|
pub fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantDef> {
|
||||||
self.imp.resolve_variant(record_lit).map(VariantDef::from)
|
self.imp.resolve_variant(record_lit).map(VariantDef::from)
|
||||||
}
|
}
|
||||||
|
@ -1242,18 +1234,6 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
self.analyze(path.syntax())?.resolve_path(self.db, path)
|
self.analyze(path.syntax())?.resolve_path(self.db, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option<Crate> {
|
|
||||||
let krate = self.scope(extern_crate.syntax())?.krate();
|
|
||||||
let name = extern_crate.name_ref()?.as_name();
|
|
||||||
if name == known::SELF_PARAM {
|
|
||||||
return Some(krate);
|
|
||||||
}
|
|
||||||
krate
|
|
||||||
.dependencies(self.db)
|
|
||||||
.into_iter()
|
|
||||||
.find_map(|dep| (dep.name == name).then_some(dep.krate))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> {
|
fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> {
|
||||||
self.analyze(record_lit.syntax())?.resolve_variant(self.db, record_lit)
|
self.analyze(record_lit.syntax())?.resolve_variant(self.db, record_lit)
|
||||||
}
|
}
|
||||||
|
@ -1603,6 +1583,7 @@ to_def_impls![
|
||||||
(crate::Local, ast::SelfParam, self_param_to_def),
|
(crate::Local, ast::SelfParam, self_param_to_def),
|
||||||
(crate::Label, ast::Label, label_to_def),
|
(crate::Label, ast::Label, label_to_def),
|
||||||
(crate::Adt, ast::Adt, adt_to_def),
|
(crate::Adt, ast::Adt, adt_to_def),
|
||||||
|
(crate::ExternCrateDecl, ast::ExternCrate, extern_crate_to_def),
|
||||||
];
|
];
|
||||||
|
|
||||||
fn find_root(node: &SyntaxNode) -> SyntaxNode {
|
fn find_root(node: &SyntaxNode) -> SyntaxNode {
|
||||||
|
|
|
@ -93,9 +93,9 @@ use hir_def::{
|
||||||
DynMap,
|
DynMap,
|
||||||
},
|
},
|
||||||
hir::{BindingId, LabelId},
|
hir::{BindingId, LabelId},
|
||||||
AdtId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId,
|
AdtId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FieldId,
|
||||||
GenericDefId, GenericParamId, ImplId, LifetimeParamId, MacroId, ModuleId, StaticId, StructId,
|
FunctionId, GenericDefId, GenericParamId, ImplId, LifetimeParamId, MacroId, ModuleId, StaticId,
|
||||||
TraitAliasId, TraitId, TypeAliasId, TypeParamId, UnionId, VariantId,
|
StructId, TraitAliasId, TraitId, TypeAliasId, TypeParamId, UnionId, VariantId,
|
||||||
};
|
};
|
||||||
use hir_expand::{attrs::AttrId, name::AsName, HirFileId, MacroCallId};
|
use hir_expand::{attrs::AttrId, name::AsName, HirFileId, MacroCallId};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
@ -203,6 +203,12 @@ impl SourceToDefCtx<'_, '_> {
|
||||||
) -> Option<EnumVariantId> {
|
) -> Option<EnumVariantId> {
|
||||||
self.to_def(src, keys::VARIANT)
|
self.to_def(src, keys::VARIANT)
|
||||||
}
|
}
|
||||||
|
pub(super) fn extern_crate_to_def(
|
||||||
|
&mut self,
|
||||||
|
src: InFile<ast::ExternCrate>,
|
||||||
|
) -> Option<ExternCrateId> {
|
||||||
|
self.to_def(src, keys::EXTERN_CRATE)
|
||||||
|
}
|
||||||
pub(super) fn adt_to_def(
|
pub(super) fn adt_to_def(
|
||||||
&mut self,
|
&mut self,
|
||||||
InFile { file_id, value }: InFile<ast::Adt>,
|
InFile { file_id, value }: InFile<ast::Adt>,
|
||||||
|
|
|
@ -42,7 +42,9 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
|
||||||
let name_ref = ast::NameRef::cast(ident.parent()?)?;
|
let name_ref = ast::NameRef::cast(ident.parent()?)?;
|
||||||
let def = match NameRefClass::classify(&ctx.sema, &name_ref)? {
|
let def = match NameRefClass::classify(&ctx.sema, &name_ref)? {
|
||||||
NameRefClass::Definition(def) => def,
|
NameRefClass::Definition(def) => def,
|
||||||
NameRefClass::FieldShorthand { .. } => return None,
|
NameRefClass::FieldShorthand { .. } | NameRefClass::ExternCrateShorthand { .. } => {
|
||||||
|
return None
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let fun = match def {
|
let fun = match def {
|
||||||
Definition::Function(it) => it,
|
Definition::Function(it) => it,
|
||||||
|
|
|
@ -7,10 +7,10 @@
|
||||||
|
|
||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
use hir::{
|
use hir::{
|
||||||
Adt, AsAssocItem, AssocItem, BuiltinAttr, BuiltinType, Const, Crate, DeriveHelper, Field,
|
Adt, AsAssocItem, AssocItem, BuiltinAttr, BuiltinType, Const, Crate, DeriveHelper,
|
||||||
Function, GenericParam, HasVisibility, Impl, Label, Local, Macro, Module, ModuleDef, Name,
|
ExternCrateDecl, Field, Function, GenericParam, HasVisibility, Impl, Label, Local, Macro,
|
||||||
PathResolution, Semantics, Static, ToolModule, Trait, TraitAlias, TypeAlias, Variant,
|
Module, ModuleDef, Name, PathResolution, Semantics, Static, ToolModule, Trait, TraitAlias,
|
||||||
Visibility,
|
TypeAlias, Variant, Visibility,
|
||||||
};
|
};
|
||||||
use stdx::impl_from;
|
use stdx::impl_from;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
|
@ -42,6 +42,7 @@ pub enum Definition {
|
||||||
DeriveHelper(DeriveHelper),
|
DeriveHelper(DeriveHelper),
|
||||||
BuiltinAttr(BuiltinAttr),
|
BuiltinAttr(BuiltinAttr),
|
||||||
ToolModule(ToolModule),
|
ToolModule(ToolModule),
|
||||||
|
ExternCrateDecl(ExternCrateDecl),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Definition {
|
impl Definition {
|
||||||
|
@ -73,6 +74,7 @@ impl Definition {
|
||||||
Definition::Local(it) => it.module(db),
|
Definition::Local(it) => it.module(db),
|
||||||
Definition::GenericParam(it) => it.module(db),
|
Definition::GenericParam(it) => it.module(db),
|
||||||
Definition::Label(it) => it.module(db),
|
Definition::Label(it) => it.module(db),
|
||||||
|
Definition::ExternCrateDecl(it) => it.module(db),
|
||||||
Definition::DeriveHelper(it) => it.derive().module(db),
|
Definition::DeriveHelper(it) => it.derive().module(db),
|
||||||
Definition::BuiltinAttr(_) | Definition::BuiltinType(_) | Definition::ToolModule(_) => {
|
Definition::BuiltinAttr(_) | Definition::BuiltinType(_) | Definition::ToolModule(_) => {
|
||||||
return None
|
return None
|
||||||
|
@ -93,6 +95,7 @@ impl Definition {
|
||||||
Definition::TraitAlias(it) => it.visibility(db),
|
Definition::TraitAlias(it) => it.visibility(db),
|
||||||
Definition::TypeAlias(it) => it.visibility(db),
|
Definition::TypeAlias(it) => it.visibility(db),
|
||||||
Definition::Variant(it) => it.visibility(db),
|
Definition::Variant(it) => it.visibility(db),
|
||||||
|
Definition::ExternCrateDecl(it) => it.visibility(db),
|
||||||
Definition::BuiltinType(_) => Visibility::Public,
|
Definition::BuiltinType(_) => Visibility::Public,
|
||||||
Definition::Macro(_) => return None,
|
Definition::Macro(_) => return None,
|
||||||
Definition::BuiltinAttr(_)
|
Definition::BuiltinAttr(_)
|
||||||
|
@ -127,6 +130,7 @@ impl Definition {
|
||||||
Definition::BuiltinAttr(_) => return None, // FIXME
|
Definition::BuiltinAttr(_) => return None, // FIXME
|
||||||
Definition::ToolModule(_) => return None, // FIXME
|
Definition::ToolModule(_) => return None, // FIXME
|
||||||
Definition::DeriveHelper(it) => it.name(db),
|
Definition::DeriveHelper(it) => it.name(db),
|
||||||
|
Definition::ExternCrateDecl(it) => return it.alias_or_name(db),
|
||||||
};
|
};
|
||||||
Some(name)
|
Some(name)
|
||||||
}
|
}
|
||||||
|
@ -196,6 +200,10 @@ impl IdentClass {
|
||||||
res.push(Definition::Local(local_ref));
|
res.push(Definition::Local(local_ref));
|
||||||
res.push(Definition::Field(field_ref));
|
res.push(Definition::Field(field_ref));
|
||||||
}
|
}
|
||||||
|
IdentClass::NameRefClass(NameRefClass::ExternCrateShorthand { decl, krate }) => {
|
||||||
|
res.push(Definition::ExternCrateDecl(decl));
|
||||||
|
res.push(Definition::Module(krate.root_module()));
|
||||||
|
}
|
||||||
IdentClass::Operator(
|
IdentClass::Operator(
|
||||||
OperatorClass::Await(func)
|
OperatorClass::Await(func)
|
||||||
| OperatorClass::Prefix(func)
|
| OperatorClass::Prefix(func)
|
||||||
|
@ -222,6 +230,10 @@ impl IdentClass {
|
||||||
res.push(Definition::Local(local_ref));
|
res.push(Definition::Local(local_ref));
|
||||||
res.push(Definition::Field(field_ref));
|
res.push(Definition::Field(field_ref));
|
||||||
}
|
}
|
||||||
|
IdentClass::NameRefClass(NameRefClass::ExternCrateShorthand { decl, krate }) => {
|
||||||
|
res.push(Definition::ExternCrateDecl(decl));
|
||||||
|
res.push(Definition::Module(krate.root_module()));
|
||||||
|
}
|
||||||
IdentClass::Operator(_) => (),
|
IdentClass::Operator(_) => (),
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
|
@ -310,6 +322,7 @@ impl NameClass {
|
||||||
ast::Item::Enum(it) => Definition::Adt(hir::Adt::Enum(sema.to_def(&it)?)),
|
ast::Item::Enum(it) => Definition::Adt(hir::Adt::Enum(sema.to_def(&it)?)),
|
||||||
ast::Item::Struct(it) => Definition::Adt(hir::Adt::Struct(sema.to_def(&it)?)),
|
ast::Item::Struct(it) => Definition::Adt(hir::Adt::Struct(sema.to_def(&it)?)),
|
||||||
ast::Item::Union(it) => Definition::Adt(hir::Adt::Union(sema.to_def(&it)?)),
|
ast::Item::Union(it) => Definition::Adt(hir::Adt::Union(sema.to_def(&it)?)),
|
||||||
|
ast::Item::ExternCrate(it) => Definition::ExternCrateDecl(sema.to_def(&it)?),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
Some(definition)
|
Some(definition)
|
||||||
|
@ -346,10 +359,8 @@ impl NameClass {
|
||||||
let path = use_tree.path()?;
|
let path = use_tree.path()?;
|
||||||
sema.resolve_path(&path).map(Definition::from)
|
sema.resolve_path(&path).map(Definition::from)
|
||||||
} else {
|
} else {
|
||||||
let extern_crate = rename.syntax().parent().and_then(ast::ExternCrate::cast)?;
|
sema.to_def(&rename.syntax().parent().and_then(ast::ExternCrate::cast)?)
|
||||||
let krate = sema.resolve_extern_crate(&extern_crate)?;
|
.map(Definition::ExternCrateDecl)
|
||||||
let root_module = krate.root_module(sema.db);
|
|
||||||
Some(Definition::Module(root_module))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -427,7 +438,19 @@ impl OperatorClass {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum NameRefClass {
|
pub enum NameRefClass {
|
||||||
Definition(Definition),
|
Definition(Definition),
|
||||||
FieldShorthand { local_ref: Local, field_ref: Field },
|
FieldShorthand {
|
||||||
|
local_ref: Local,
|
||||||
|
field_ref: Field,
|
||||||
|
},
|
||||||
|
/// The specific situation where we have an extern crate decl without a rename
|
||||||
|
/// Here we have both a declaration and a reference.
|
||||||
|
/// ```rs
|
||||||
|
/// extern crate foo;
|
||||||
|
/// ```
|
||||||
|
ExternCrateShorthand {
|
||||||
|
decl: ExternCrateDecl,
|
||||||
|
krate: Crate,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NameRefClass {
|
impl NameRefClass {
|
||||||
|
@ -513,10 +536,14 @@ impl NameRefClass {
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
ast::ExternCrate(extern_crate) => {
|
ast::ExternCrate(extern_crate_ast) => {
|
||||||
let krate = sema.resolve_extern_crate(&extern_crate)?;
|
let extern_crate = sema.to_def(&extern_crate_ast)?;
|
||||||
let root_module = krate.root_module(sema.db);
|
let krate = extern_crate.resolved_crate(sema.db);
|
||||||
Some(NameRefClass::Definition(Definition::Module(root_module)))
|
Some(if extern_crate_ast.rename().is_some() {
|
||||||
|
NameRefClass::Definition(Definition::Module(krate.root_module()))
|
||||||
|
} else {
|
||||||
|
NameRefClass::ExternCrateShorthand { krate, decl: extern_crate }
|
||||||
|
})
|
||||||
},
|
},
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,7 +167,7 @@ impl FamousDefs<'_, '_> {
|
||||||
lang_crate => lang_crate,
|
lang_crate => lang_crate,
|
||||||
};
|
};
|
||||||
let std_crate = self.find_lang_crate(lang_crate)?;
|
let std_crate = self.find_lang_crate(lang_crate)?;
|
||||||
let mut module = std_crate.root_module(db);
|
let mut module = std_crate.root_module();
|
||||||
for segment in path {
|
for segment in path {
|
||||||
module = module.children(db).find_map(|child| {
|
module = module.children(db).find_map(|child| {
|
||||||
let name = child.name(db)?;
|
let name = child.name(db)?;
|
||||||
|
|
|
@ -82,8 +82,9 @@ impl Definition {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Textual range of the identifier which will change when renaming this
|
/// Textual range of the identifier which will change when renaming this
|
||||||
/// `Definition`. Note that some definitions, like builtin types, can't be
|
/// `Definition`. Note that builtin types can't be
|
||||||
/// renamed.
|
/// renamed and extern crate names will report its range, though a rename will introduce
|
||||||
|
/// an alias instead.
|
||||||
pub fn range_for_rename(self, sema: &Semantics<'_, RootDatabase>) -> Option<FileRange> {
|
pub fn range_for_rename(self, sema: &Semantics<'_, RootDatabase>) -> Option<FileRange> {
|
||||||
let res = match self {
|
let res = match self {
|
||||||
Definition::Macro(mac) => {
|
Definition::Macro(mac) => {
|
||||||
|
@ -146,6 +147,16 @@ impl Definition {
|
||||||
let lifetime = src.value.lifetime()?;
|
let lifetime = src.value.lifetime()?;
|
||||||
src.with_value(lifetime.syntax()).original_file_range_opt(sema.db)
|
src.with_value(lifetime.syntax()).original_file_range_opt(sema.db)
|
||||||
}
|
}
|
||||||
|
Definition::ExternCrateDecl(it) => {
|
||||||
|
let src = it.source(sema.db)?;
|
||||||
|
if let Some(rename) = src.value.rename() {
|
||||||
|
let name = rename.name()?;
|
||||||
|
src.with_value(name.syntax()).original_file_range_opt(sema.db)
|
||||||
|
} else {
|
||||||
|
let name = src.value.name_ref()?;
|
||||||
|
src.with_value(name.syntax()).original_file_range_opt(sema.db)
|
||||||
|
}
|
||||||
|
}
|
||||||
Definition::BuiltinType(_) => return None,
|
Definition::BuiltinType(_) => return None,
|
||||||
Definition::SelfType(_) => return None,
|
Definition::SelfType(_) => return None,
|
||||||
Definition::BuiltinAttr(_) => return None,
|
Definition::BuiltinAttr(_) => return None,
|
||||||
|
@ -526,6 +537,9 @@ fn source_edit_from_def(
|
||||||
TextRange::new(range.start() + syntax::TextSize::from(1), range.end()),
|
TextRange::new(range.start() + syntax::TextSize::from(1), range.end()),
|
||||||
new_name.strip_prefix('\'').unwrap_or(new_name).to_owned(),
|
new_name.strip_prefix('\'').unwrap_or(new_name).to_owned(),
|
||||||
),
|
),
|
||||||
|
Definition::ExternCrateDecl(decl) if decl.alias(sema.db).is_none() => {
|
||||||
|
(TextRange::empty(range.end()), format!(" as {new_name}"))
|
||||||
|
}
|
||||||
_ => (range, new_name.to_owned()),
|
_ => (range, new_name.to_owned()),
|
||||||
};
|
};
|
||||||
edit.replace(range, new_name);
|
edit.replace(range, new_name);
|
||||||
|
|
|
@ -208,7 +208,7 @@ fn get_default_constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
let krate = ctx.sema.to_module_def(d.file.original_file(ctx.sema.db))?.krate();
|
let krate = ctx.sema.to_module_def(d.file.original_file(ctx.sema.db))?.krate();
|
||||||
let module = krate.root_module(ctx.sema.db);
|
let module = krate.root_module();
|
||||||
|
|
||||||
// Look for a ::new() associated function
|
// Look for a ::new() associated function
|
||||||
let has_new_func = ty
|
let has_new_func = ty
|
||||||
|
|
|
@ -153,6 +153,9 @@ pub(crate) fn external_docs(
|
||||||
NameRefClass::FieldShorthand { local_ref: _, field_ref } => {
|
NameRefClass::FieldShorthand { local_ref: _, field_ref } => {
|
||||||
Definition::Field(field_ref)
|
Definition::Field(field_ref)
|
||||||
}
|
}
|
||||||
|
NameRefClass::ExternCrateShorthand { decl, .. } => {
|
||||||
|
Definition::ExternCrateDecl(decl)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
ast::Name(name) => match NameClass::classify(sema, &name)? {
|
ast::Name(name) => match NameClass::classify(sema, &name)? {
|
||||||
NameClass::Definition(it) | NameClass::ConstReference(it) => it,
|
NameClass::Definition(it) | NameClass::ConstReference(it) => it,
|
||||||
|
@ -209,6 +212,7 @@ pub(crate) fn resolve_doc_path_for_def(
|
||||||
Definition::Macro(it) => it.resolve_doc_path(db, link, ns),
|
Definition::Macro(it) => it.resolve_doc_path(db, link, ns),
|
||||||
Definition::Field(it) => it.resolve_doc_path(db, link, ns),
|
Definition::Field(it) => it.resolve_doc_path(db, link, ns),
|
||||||
Definition::SelfType(it) => it.resolve_doc_path(db, link, ns),
|
Definition::SelfType(it) => it.resolve_doc_path(db, link, ns),
|
||||||
|
Definition::ExternCrateDecl(it) => it.resolve_doc_path(db, link, ns),
|
||||||
Definition::BuiltinAttr(_)
|
Definition::BuiltinAttr(_)
|
||||||
| Definition::ToolModule(_)
|
| Definition::ToolModule(_)
|
||||||
| Definition::BuiltinType(_)
|
| Definition::BuiltinType(_)
|
||||||
|
@ -617,6 +621,9 @@ fn filename_and_frag_for_def(
|
||||||
// FIXME fragment numbering
|
// FIXME fragment numbering
|
||||||
return Some((adt, file, Some(String::from("impl"))));
|
return Some((adt, file, Some(String::from("impl"))));
|
||||||
}
|
}
|
||||||
|
Definition::ExternCrateDecl(it) => {
|
||||||
|
format!("{}/index.html", it.name(db).display(db.upcast()))
|
||||||
|
}
|
||||||
Definition::Local(_)
|
Definition::Local(_)
|
||||||
| Definition::GenericParam(_)
|
| Definition::GenericParam(_)
|
||||||
| Definition::Label(_)
|
| Definition::Label(_)
|
||||||
|
|
|
@ -37,11 +37,15 @@ pub(crate) fn goto_declaration(
|
||||||
match parent {
|
match parent {
|
||||||
ast::NameRef(name_ref) => match NameRefClass::classify(&sema, &name_ref)? {
|
ast::NameRef(name_ref) => match NameRefClass::classify(&sema, &name_ref)? {
|
||||||
NameRefClass::Definition(it) => Some(it),
|
NameRefClass::Definition(it) => Some(it),
|
||||||
NameRefClass::FieldShorthand { field_ref, .. } => return field_ref.try_to_nav(db),
|
NameRefClass::FieldShorthand { field_ref, .. } =>
|
||||||
|
return field_ref.try_to_nav(db),
|
||||||
|
NameRefClass::ExternCrateShorthand { decl, .. } =>
|
||||||
|
return decl.try_to_nav(db),
|
||||||
},
|
},
|
||||||
ast::Name(name) => match NameClass::classify(&sema, &name)? {
|
ast::Name(name) => match NameClass::classify(&sema, &name)? {
|
||||||
NameClass::Definition(it) | NameClass::ConstReference(it) => Some(it),
|
NameClass::Definition(it) | NameClass::ConstReference(it) => Some(it),
|
||||||
NameClass::PatFieldShorthand { field_ref, .. } => return field_ref.try_to_nav(db),
|
NameClass::PatFieldShorthand { field_ref, .. } =>
|
||||||
|
return field_ref.try_to_nav(db),
|
||||||
},
|
},
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
|
@ -53,6 +57,7 @@ pub(crate) fn goto_declaration(
|
||||||
Definition::Const(c) => c.as_assoc_item(db),
|
Definition::Const(c) => c.as_assoc_item(db),
|
||||||
Definition::TypeAlias(ta) => ta.as_assoc_item(db),
|
Definition::TypeAlias(ta) => ta.as_assoc_item(db),
|
||||||
Definition::Function(f) => f.as_assoc_item(db),
|
Definition::Function(f) => f.as_assoc_item(db),
|
||||||
|
Definition::ExternCrateDecl(it) => return it.try_to_nav(db),
|
||||||
_ => None,
|
_ => None,
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
|
@ -211,4 +216,30 @@ fn main() {
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_decl_for_extern_crate() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
//- /main.rs crate:main deps:std
|
||||||
|
extern crate std$0;
|
||||||
|
/// ^^^
|
||||||
|
//- /std/lib.rs crate:std
|
||||||
|
// empty
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_decl_for_renamed_extern_crate() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
//- /main.rs crate:main deps:std
|
||||||
|
extern crate std as abc$0;
|
||||||
|
/// ^^^
|
||||||
|
//- /std/lib.rs crate:std
|
||||||
|
// empty
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use std::mem::discriminant;
|
use std::mem::discriminant;
|
||||||
|
|
||||||
use crate::{doc_links::token_as_doc_comment, FilePosition, NavigationTarget, RangeInfo, TryToNav};
|
use crate::{
|
||||||
|
doc_links::token_as_doc_comment, navigation_target::ToNav, FilePosition, NavigationTarget,
|
||||||
|
RangeInfo, TryToNav,
|
||||||
|
};
|
||||||
use hir::{AsAssocItem, AssocItem, Semantics};
|
use hir::{AsAssocItem, AssocItem, Semantics};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
base_db::{AnchoredPath, FileId, FileLoader},
|
base_db::{AnchoredPath, FileId, FileLoader},
|
||||||
|
@ -73,6 +76,12 @@ pub(crate) fn goto_definition(
|
||||||
.definitions()
|
.definitions()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|def| {
|
.flat_map(|def| {
|
||||||
|
if let Definition::ExternCrateDecl(crate_def) = def {
|
||||||
|
return vec![crate_def
|
||||||
|
.resolved_crate(db)
|
||||||
|
.root_module()
|
||||||
|
.to_nav(sema.db)];
|
||||||
|
}
|
||||||
try_filter_trait_item_definition(sema, &def)
|
try_filter_trait_item_definition(sema, &def)
|
||||||
.unwrap_or_else(|| def_to_nav(sema.db, def))
|
.unwrap_or_else(|| def_to_nav(sema.db, def))
|
||||||
})
|
})
|
||||||
|
|
|
@ -34,54 +34,50 @@ pub(crate) fn goto_implementation(
|
||||||
_ => 0,
|
_ => 0,
|
||||||
})?;
|
})?;
|
||||||
let range = original_token.text_range();
|
let range = original_token.text_range();
|
||||||
let navs = sema
|
let navs =
|
||||||
.descend_into_macros(original_token)
|
sema.descend_into_macros(original_token)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|token| token.parent().and_then(ast::NameLike::cast))
|
.filter_map(|token| token.parent().and_then(ast::NameLike::cast))
|
||||||
.filter_map(|node| match &node {
|
.filter_map(|node| match &node {
|
||||||
ast::NameLike::Name(name) => {
|
ast::NameLike::Name(name) => {
|
||||||
NameClass::classify(&sema, name).map(|class| match class {
|
NameClass::classify(&sema, name).and_then(|class| match class {
|
||||||
NameClass::Definition(it) | NameClass::ConstReference(it) => it,
|
NameClass::Definition(it) | NameClass::ConstReference(it) => Some(it),
|
||||||
NameClass::PatFieldShorthand { local_def, field_ref: _ } => {
|
NameClass::PatFieldShorthand { .. } => None,
|
||||||
Definition::Local(local_def)
|
})
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
ast::NameLike::NameRef(name_ref) => {
|
|
||||||
NameRefClass::classify(&sema, name_ref).map(|class| match class {
|
|
||||||
NameRefClass::Definition(def) => def,
|
|
||||||
NameRefClass::FieldShorthand { local_ref, field_ref: _ } => {
|
|
||||||
Definition::Local(local_ref)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
ast::NameLike::Lifetime(_) => None,
|
|
||||||
})
|
|
||||||
.unique()
|
|
||||||
.filter_map(|def| {
|
|
||||||
let navs = match def {
|
|
||||||
Definition::Trait(trait_) => impls_for_trait(&sema, trait_),
|
|
||||||
Definition::Adt(adt) => impls_for_ty(&sema, adt.ty(sema.db)),
|
|
||||||
Definition::TypeAlias(alias) => impls_for_ty(&sema, alias.ty(sema.db)),
|
|
||||||
Definition::BuiltinType(builtin) => impls_for_ty(&sema, builtin.ty(sema.db)),
|
|
||||||
Definition::Function(f) => {
|
|
||||||
let assoc = f.as_assoc_item(sema.db)?;
|
|
||||||
let name = assoc.name(sema.db)?;
|
|
||||||
let trait_ = assoc.containing_trait_or_trait_impl(sema.db)?;
|
|
||||||
impls_for_trait_item(&sema, trait_, name)
|
|
||||||
}
|
}
|
||||||
Definition::Const(c) => {
|
ast::NameLike::NameRef(name_ref) => NameRefClass::classify(&sema, name_ref)
|
||||||
let assoc = c.as_assoc_item(sema.db)?;
|
.and_then(|class| match class {
|
||||||
let name = assoc.name(sema.db)?;
|
NameRefClass::Definition(def) => Some(def),
|
||||||
let trait_ = assoc.containing_trait_or_trait_impl(sema.db)?;
|
NameRefClass::FieldShorthand { .. }
|
||||||
impls_for_trait_item(&sema, trait_, name)
|
| NameRefClass::ExternCrateShorthand { .. } => None,
|
||||||
}
|
}),
|
||||||
_ => return None,
|
ast::NameLike::Lifetime(_) => None,
|
||||||
};
|
})
|
||||||
Some(navs)
|
.unique()
|
||||||
})
|
.filter_map(|def| {
|
||||||
.flatten()
|
let navs = match def {
|
||||||
.collect();
|
Definition::Trait(trait_) => impls_for_trait(&sema, trait_),
|
||||||
|
Definition::Adt(adt) => impls_for_ty(&sema, adt.ty(sema.db)),
|
||||||
|
Definition::TypeAlias(alias) => impls_for_ty(&sema, alias.ty(sema.db)),
|
||||||
|
Definition::BuiltinType(builtin) => impls_for_ty(&sema, builtin.ty(sema.db)),
|
||||||
|
Definition::Function(f) => {
|
||||||
|
let assoc = f.as_assoc_item(sema.db)?;
|
||||||
|
let name = assoc.name(sema.db)?;
|
||||||
|
let trait_ = assoc.containing_trait_or_trait_impl(sema.db)?;
|
||||||
|
impls_for_trait_item(&sema, trait_, name)
|
||||||
|
}
|
||||||
|
Definition::Const(c) => {
|
||||||
|
let assoc = c.as_assoc_item(sema.db)?;
|
||||||
|
let name = assoc.name(sema.db)?;
|
||||||
|
let trait_ = assoc.containing_trait_or_trait_impl(sema.db)?;
|
||||||
|
impls_for_trait_item(&sema, trait_, name)
|
||||||
|
}
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
Some(navs)
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
.collect();
|
||||||
|
|
||||||
Some(RangeInfo { range, info: navs })
|
Some(RangeInfo { range, info: navs })
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use either::Either;
|
||||||
use hir::{db::DefDatabase, HasSource, LangItem, Semantics};
|
use hir::{db::DefDatabase, HasSource, LangItem, Semantics};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
base_db::FileRange,
|
base_db::FileRange,
|
||||||
defs::{Definition, IdentClass, OperatorClass},
|
defs::{Definition, IdentClass, NameRefClass, OperatorClass},
|
||||||
famous_defs::FamousDefs,
|
famous_defs::FamousDefs,
|
||||||
helpers::pick_best_token,
|
helpers::pick_best_token,
|
||||||
FxIndexSet, RootDatabase,
|
FxIndexSet, RootDatabase,
|
||||||
|
@ -186,7 +186,20 @@ fn hover_simple(
|
||||||
// rendering poll is very confusing
|
// rendering poll is very confusing
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Some(class.definitions().into_iter().zip(iter::once(node).cycle()))
|
if let IdentClass::NameRefClass(NameRefClass::ExternCrateShorthand {
|
||||||
|
decl,
|
||||||
|
..
|
||||||
|
}) = class
|
||||||
|
{
|
||||||
|
return Some(vec![(Definition::ExternCrateDecl(decl), node)]);
|
||||||
|
}
|
||||||
|
Some(
|
||||||
|
class
|
||||||
|
.definitions()
|
||||||
|
.into_iter()
|
||||||
|
.zip(iter::once(node).cycle())
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.flatten()
|
.flatten()
|
||||||
.unique_by(|&(def, _)| def)
|
.unique_by(|&(def, _)| def)
|
||||||
|
|
|
@ -257,7 +257,7 @@ pub(super) fn keyword(
|
||||||
let KeywordHint { description, keyword_mod, actions } = keyword_hints(sema, token, parent);
|
let KeywordHint { description, keyword_mod, actions } = keyword_hints(sema, token, parent);
|
||||||
|
|
||||||
let doc_owner = find_std_module(&famous_defs, &keyword_mod)?;
|
let doc_owner = find_std_module(&famous_defs, &keyword_mod)?;
|
||||||
let docs = doc_owner.attrs(sema.db).docs()?;
|
let docs = doc_owner.docs(sema.db)?;
|
||||||
let markup = process_markup(
|
let markup = process_markup(
|
||||||
sema.db,
|
sema.db,
|
||||||
Definition::Module(doc_owner),
|
Definition::Module(doc_owner),
|
||||||
|
@ -472,6 +472,7 @@ pub(super) fn definition(
|
||||||
}
|
}
|
||||||
Definition::GenericParam(it) => label_and_docs(db, it),
|
Definition::GenericParam(it) => label_and_docs(db, it),
|
||||||
Definition::Label(it) => return Some(Markup::fenced_block(&it.name(db).display(db))),
|
Definition::Label(it) => return Some(Markup::fenced_block(&it.name(db).display(db))),
|
||||||
|
Definition::ExternCrateDecl(it) => label_and_docs(db, it),
|
||||||
// FIXME: We should be able to show more info about these
|
// FIXME: We should be able to show more info about these
|
||||||
Definition::BuiltinAttr(it) => return render_builtin_attr(db, it),
|
Definition::BuiltinAttr(it) => return render_builtin_attr(db, it),
|
||||||
Definition::ToolModule(it) => return Some(Markup::fenced_block(&it.name(db))),
|
Definition::ToolModule(it) => return Some(Markup::fenced_block(&it.name(db))),
|
||||||
|
@ -620,7 +621,7 @@ where
|
||||||
D: HasAttrs + HirDisplay,
|
D: HasAttrs + HirDisplay,
|
||||||
{
|
{
|
||||||
let label = def.display(db).to_string();
|
let label = def.display(db).to_string();
|
||||||
let docs = def.attrs(db).docs();
|
let docs = def.docs(db);
|
||||||
(label, docs)
|
(label, docs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,7 +646,7 @@ where
|
||||||
) {
|
) {
|
||||||
format_to!(label, "{layout}");
|
format_to!(label, "{layout}");
|
||||||
}
|
}
|
||||||
let docs = def.attrs(db).docs();
|
let docs = def.docs(db);
|
||||||
(label, docs)
|
(label, docs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -677,7 +678,7 @@ where
|
||||||
) {
|
) {
|
||||||
format_to!(label, "{layout}");
|
format_to!(label, "{layout}");
|
||||||
}
|
}
|
||||||
let docs = def.attrs(db).docs();
|
let docs = def.docs(db);
|
||||||
(label, docs)
|
(label, docs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -696,7 +697,7 @@ where
|
||||||
} else {
|
} else {
|
||||||
def.display(db).to_string()
|
def.display(db).to_string()
|
||||||
};
|
};
|
||||||
let docs = def.attrs(db).docs();
|
let docs = def.docs(db);
|
||||||
(label, docs)
|
(label, docs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -727,14 +728,14 @@ fn builtin(famous_defs: &FamousDefs<'_, '_>, builtin: hir::BuiltinType) -> Optio
|
||||||
// std exposes prim_{} modules with docstrings on the root to document the builtins
|
// std exposes prim_{} modules with docstrings on the root to document the builtins
|
||||||
let primitive_mod = format!("prim_{}", builtin.name().display(famous_defs.0.db));
|
let primitive_mod = format!("prim_{}", builtin.name().display(famous_defs.0.db));
|
||||||
let doc_owner = find_std_module(famous_defs, &primitive_mod)?;
|
let doc_owner = find_std_module(famous_defs, &primitive_mod)?;
|
||||||
let docs = doc_owner.attrs(famous_defs.0.db).docs()?;
|
let docs = doc_owner.docs(famous_defs.0.db)?;
|
||||||
markup(Some(docs.into()), builtin.name().display(famous_defs.0.db).to_string(), None)
|
markup(Some(docs.into()), builtin.name().display(famous_defs.0.db).to_string(), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_std_module(famous_defs: &FamousDefs<'_, '_>, name: &str) -> Option<hir::Module> {
|
fn find_std_module(famous_defs: &FamousDefs<'_, '_>, name: &str) -> Option<hir::Module> {
|
||||||
let db = famous_defs.0.db;
|
let db = famous_defs.0.db;
|
||||||
let std_crate = famous_defs.std()?;
|
let std_crate = famous_defs.std()?;
|
||||||
let std_root_module = std_crate.root_module(db);
|
let std_root_module = std_crate.root_module();
|
||||||
std_root_module.children(db).find(|module| {
|
std_root_module.children(db).find(|module| {
|
||||||
module.name(db).map_or(false, |module| module.display(db).to_string() == name)
|
module.name(db).map_or(false, |module| module.display(db).to_string() == name)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1616,6 +1616,9 @@ fn test_hover_extern_crate() {
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
//- /main.rs crate:main deps:std
|
//- /main.rs crate:main deps:std
|
||||||
|
//! Crate docs
|
||||||
|
|
||||||
|
/// Decl docs!
|
||||||
extern crate st$0d;
|
extern crate st$0d;
|
||||||
//- /std/lib.rs crate:std
|
//- /std/lib.rs crate:std
|
||||||
//! Standard library for this test
|
//! Standard library for this test
|
||||||
|
@ -1624,23 +1627,32 @@ extern crate st$0d;
|
||||||
//! abc123
|
//! abc123
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
*std*
|
*std*
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
extern crate std
|
main
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
```rust
|
||||||
|
extern crate std
|
||||||
|
```
|
||||||
|
|
||||||
Standard library for this test
|
---
|
||||||
|
|
||||||
Printed?
|
Decl docs!
|
||||||
abc123
|
|
||||||
"#]],
|
Standard library for this test
|
||||||
|
|
||||||
|
Printed?
|
||||||
|
abc123
|
||||||
|
"#]],
|
||||||
);
|
);
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
//- /main.rs crate:main deps:std
|
//- /main.rs crate:main deps:std
|
||||||
|
//! Crate docs
|
||||||
|
|
||||||
|
/// Decl docs!
|
||||||
extern crate std as ab$0c;
|
extern crate std as ab$0c;
|
||||||
//- /std/lib.rs crate:std
|
//- /std/lib.rs crate:std
|
||||||
//! Standard library for this test
|
//! Standard library for this test
|
||||||
|
@ -1649,19 +1661,25 @@ extern crate std as ab$0c;
|
||||||
//! abc123
|
//! abc123
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
*abc*
|
*abc*
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
extern crate std
|
main
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
```rust
|
||||||
|
extern crate std as abc
|
||||||
|
```
|
||||||
|
|
||||||
Standard library for this test
|
---
|
||||||
|
|
||||||
Printed?
|
Decl docs!
|
||||||
abc123
|
|
||||||
"#]],
|
Standard library for this test
|
||||||
|
|
||||||
|
Printed?
|
||||||
|
abc123
|
||||||
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -247,6 +247,10 @@ pub(crate) fn def_to_moniker(
|
||||||
name: s.name(db).display(db).to_string(),
|
name: s.name(db).display(db).to_string(),
|
||||||
desc: MonikerDescriptorKind::Meta,
|
desc: MonikerDescriptorKind::Meta,
|
||||||
},
|
},
|
||||||
|
Definition::ExternCrateDecl(m) => MonikerDescriptor {
|
||||||
|
name: m.name(db).display(db).to_string(),
|
||||||
|
desc: MonikerDescriptorKind::Namespace,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
description.push(name_desc);
|
description.push(name_desc);
|
||||||
|
|
|
@ -102,7 +102,7 @@ impl NavigationTarget {
|
||||||
full_range,
|
full_range,
|
||||||
SymbolKind::Module,
|
SymbolKind::Module,
|
||||||
);
|
);
|
||||||
res.docs = module.attrs(db).docs();
|
res.docs = module.docs(db);
|
||||||
res.description = Some(module.display(db).to_string());
|
res.description = Some(module.display(db).to_string());
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -217,6 +217,7 @@ impl TryToNav for Definition {
|
||||||
Definition::Trait(it) => it.try_to_nav(db),
|
Definition::Trait(it) => it.try_to_nav(db),
|
||||||
Definition::TraitAlias(it) => it.try_to_nav(db),
|
Definition::TraitAlias(it) => it.try_to_nav(db),
|
||||||
Definition::TypeAlias(it) => it.try_to_nav(db),
|
Definition::TypeAlias(it) => it.try_to_nav(db),
|
||||||
|
Definition::ExternCrateDecl(it) => Some(it.try_to_nav(db)?),
|
||||||
Definition::BuiltinType(_) => None,
|
Definition::BuiltinType(_) => None,
|
||||||
Definition::ToolModule(_) => None,
|
Definition::ToolModule(_) => None,
|
||||||
Definition::BuiltinAttr(_) => None,
|
Definition::BuiltinAttr(_) => None,
|
||||||
|
@ -375,6 +376,30 @@ impl TryToNav for hir::Impl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TryToNav for hir::ExternCrateDecl {
|
||||||
|
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||||
|
let src = self.source(db)?;
|
||||||
|
let InFile { file_id, value } = src;
|
||||||
|
let focus = value
|
||||||
|
.rename()
|
||||||
|
.map_or_else(|| value.name_ref().map(Either::Left), |it| it.name().map(Either::Right));
|
||||||
|
let (file_id, full_range, focus_range) =
|
||||||
|
orig_range_with_focus(db, file_id, value.syntax(), focus);
|
||||||
|
let mut res = NavigationTarget::from_syntax(
|
||||||
|
file_id,
|
||||||
|
self.alias_or_name(db).unwrap_or_else(|| self.name(db)).to_smol_str(),
|
||||||
|
focus_range,
|
||||||
|
full_range,
|
||||||
|
SymbolKind::Module,
|
||||||
|
);
|
||||||
|
|
||||||
|
res.docs = self.docs(db);
|
||||||
|
res.description = Some(self.display(db).to_string());
|
||||||
|
res.container_name = container_name(db, *self);
|
||||||
|
Some(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TryToNav for hir::Field {
|
impl TryToNav for hir::Field {
|
||||||
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
|
||||||
let src = self.source(db)?;
|
let src = self.source(db)?;
|
||||||
|
|
|
@ -137,6 +137,9 @@ pub(crate) fn find_defs<'a>(
|
||||||
NameRefClass::FieldShorthand { local_ref, field_ref: _ } => {
|
NameRefClass::FieldShorthand { local_ref, field_ref: _ } => {
|
||||||
Definition::Local(local_ref)
|
Definition::Local(local_ref)
|
||||||
}
|
}
|
||||||
|
NameRefClass::ExternCrateShorthand { decl, .. } => {
|
||||||
|
Definition::ExternCrateDecl(decl)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::NameLike::Name(name) => match NameClass::classify(sema, &name)? {
|
ast::NameLike::Name(name) => match NameClass::classify(sema, &name)? {
|
||||||
|
|
|
@ -145,7 +145,14 @@ fn find_definitions(
|
||||||
if name
|
if name
|
||||||
.syntax()
|
.syntax()
|
||||||
.parent()
|
.parent()
|
||||||
.map_or(false, |it| ast::Rename::can_cast(it.kind())) =>
|
.map_or(false, |it| ast::Rename::can_cast(it.kind()))
|
||||||
|
// FIXME: uncomment this once we resolve to usages to extern crate declarations
|
||||||
|
// && name
|
||||||
|
// .syntax()
|
||||||
|
// .ancestors()
|
||||||
|
// .nth(2)
|
||||||
|
// .map_or(true, |it| !ast::ExternCrate::can_cast(it.kind()))
|
||||||
|
=>
|
||||||
{
|
{
|
||||||
bail!("Renaming aliases is currently unsupported")
|
bail!("Renaming aliases is currently unsupported")
|
||||||
}
|
}
|
||||||
|
@ -165,7 +172,12 @@ fn find_definitions(
|
||||||
NameRefClass::FieldShorthand { local_ref, field_ref: _ } => {
|
NameRefClass::FieldShorthand { local_ref, field_ref: _ } => {
|
||||||
Definition::Local(local_ref)
|
Definition::Local(local_ref)
|
||||||
}
|
}
|
||||||
|
NameRefClass::ExternCrateShorthand { decl, .. } => {
|
||||||
|
Definition::ExternCrateDecl(decl)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
// FIXME: uncomment this once we resolve to usages to extern crate declarations
|
||||||
|
.filter(|def| !matches!(def, Definition::ExternCrateDecl(..)))
|
||||||
.ok_or_else(|| format_err!("No references found at position"))
|
.ok_or_else(|| format_err!("No references found at position"))
|
||||||
.and_then(|def| {
|
.and_then(|def| {
|
||||||
// if the name differs from the definitions name it has to be an alias
|
// if the name differs from the definitions name it has to be an alias
|
||||||
|
@ -2517,4 +2529,109 @@ fn main() {
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extern_crate() {
|
||||||
|
check_prepare(
|
||||||
|
r"
|
||||||
|
//- /lib.rs crate:main deps:foo
|
||||||
|
extern crate foo$0;
|
||||||
|
use foo as qux;
|
||||||
|
//- /foo.rs crate:foo
|
||||||
|
",
|
||||||
|
expect![[r#"No references found at position"#]],
|
||||||
|
);
|
||||||
|
// FIXME: replace above check_prepare with this once we resolve to usages to extern crate declarations
|
||||||
|
// check(
|
||||||
|
// "bar",
|
||||||
|
// r"
|
||||||
|
// //- /lib.rs crate:main deps:foo
|
||||||
|
// extern crate foo$0;
|
||||||
|
// use foo as qux;
|
||||||
|
// //- /foo.rs crate:foo
|
||||||
|
// ",
|
||||||
|
// r"
|
||||||
|
// extern crate foo as bar;
|
||||||
|
// use bar as qux;
|
||||||
|
// ",
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extern_crate_rename() {
|
||||||
|
check_prepare(
|
||||||
|
r"
|
||||||
|
//- /lib.rs crate:main deps:foo
|
||||||
|
extern crate foo as qux$0;
|
||||||
|
use qux as frob;
|
||||||
|
//- /foo.rs crate:foo
|
||||||
|
",
|
||||||
|
expect!["Renaming aliases is currently unsupported"],
|
||||||
|
);
|
||||||
|
// FIXME: replace above check_prepare with this once we resolve to usages to extern crate
|
||||||
|
// declarations
|
||||||
|
// check(
|
||||||
|
// "bar",
|
||||||
|
// r"
|
||||||
|
// //- /lib.rs crate:main deps:foo
|
||||||
|
// extern crate foo as qux$0;
|
||||||
|
// use qux as frob;
|
||||||
|
// //- /foo.rs crate:foo
|
||||||
|
// ",
|
||||||
|
// r"
|
||||||
|
// extern crate foo as bar;
|
||||||
|
// use bar as frob;
|
||||||
|
// ",
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extern_crate_self() {
|
||||||
|
check_prepare(
|
||||||
|
r"
|
||||||
|
extern crate self$0;
|
||||||
|
use self as qux;
|
||||||
|
",
|
||||||
|
expect!["No references found at position"],
|
||||||
|
);
|
||||||
|
// FIXME: replace above check_prepare with this once we resolve to usages to extern crate declarations
|
||||||
|
// check(
|
||||||
|
// "bar",
|
||||||
|
// r"
|
||||||
|
// extern crate self$0;
|
||||||
|
// use self as qux;
|
||||||
|
// ",
|
||||||
|
// r"
|
||||||
|
// extern crate self as bar;
|
||||||
|
// use self as qux;
|
||||||
|
// ",
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extern_crate_self_rename() {
|
||||||
|
check_prepare(
|
||||||
|
r"
|
||||||
|
//- /lib.rs crate:main deps:foo
|
||||||
|
extern crate self as qux$0;
|
||||||
|
use qux as frob;
|
||||||
|
//- /foo.rs crate:foo
|
||||||
|
",
|
||||||
|
expect!["Renaming aliases is currently unsupported"],
|
||||||
|
);
|
||||||
|
// FIXME: replace above check_prepare with this once we resolve to usages to extern crate declarations
|
||||||
|
// check(
|
||||||
|
// "bar",
|
||||||
|
// r"
|
||||||
|
// //- /lib.rs crate:main deps:foo
|
||||||
|
// extern crate self as qux$0;
|
||||||
|
// use qux as frob;
|
||||||
|
// //- /foo.rs crate:foo
|
||||||
|
// ",
|
||||||
|
// r"
|
||||||
|
// extern crate self as bar;
|
||||||
|
// use bar as frob;
|
||||||
|
// ",
|
||||||
|
// );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -309,7 +309,7 @@ pub(crate) fn runnable_fn(
|
||||||
) -> Option<Runnable> {
|
) -> Option<Runnable> {
|
||||||
let name = def.name(sema.db).to_smol_str();
|
let name = def.name(sema.db).to_smol_str();
|
||||||
|
|
||||||
let root = def.module(sema.db).krate().root_module(sema.db);
|
let root = def.module(sema.db).krate().root_module();
|
||||||
|
|
||||||
let kind = if name == "main" && def.module(sema.db) == root {
|
let kind = if name == "main" && def.module(sema.db) == root {
|
||||||
RunnableKind::Bin
|
RunnableKind::Bin
|
||||||
|
|
|
@ -88,7 +88,7 @@ pub struct StaticIndexedFile {
|
||||||
|
|
||||||
fn all_modules(db: &dyn HirDatabase) -> Vec<Module> {
|
fn all_modules(db: &dyn HirDatabase) -> Vec<Module> {
|
||||||
let mut worklist: Vec<_> =
|
let mut worklist: Vec<_> =
|
||||||
Crate::all(db).into_iter().map(|krate| krate.root_module(db)).collect();
|
Crate::all(db).into_iter().map(|krate| krate.root_module()).collect();
|
||||||
let mut modules = Vec::new();
|
let mut modules = Vec::new();
|
||||||
|
|
||||||
while let Some(module) = worklist.pop() {
|
while let Some(module) = worklist.pop() {
|
||||||
|
|
|
@ -269,7 +269,26 @@ fn highlight_name_ref(
|
||||||
|
|
||||||
h
|
h
|
||||||
}
|
}
|
||||||
NameRefClass::FieldShorthand { .. } => SymbolKind::Field.into(),
|
NameRefClass::FieldShorthand { field_ref, .. } => {
|
||||||
|
highlight_def(sema, krate, field_ref.into())
|
||||||
|
}
|
||||||
|
NameRefClass::ExternCrateShorthand { decl, krate: resolved_krate } => {
|
||||||
|
let mut h = HlTag::Symbol(SymbolKind::Module).into();
|
||||||
|
|
||||||
|
if resolved_krate != krate {
|
||||||
|
h |= HlMod::Library
|
||||||
|
}
|
||||||
|
let is_public = decl.visibility(db) == hir::Visibility::Public;
|
||||||
|
if is_public {
|
||||||
|
h |= HlMod::Public
|
||||||
|
}
|
||||||
|
let is_from_builtin_crate = resolved_krate.is_builtin(db);
|
||||||
|
if is_from_builtin_crate {
|
||||||
|
h |= HlMod::DefaultLibrary;
|
||||||
|
}
|
||||||
|
h |= HlMod::CrateRoot;
|
||||||
|
h
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
h.tag = match name_ref.token_kind() {
|
h.tag = match name_ref.token_kind() {
|
||||||
|
@ -474,6 +493,14 @@ fn highlight_def(
|
||||||
}
|
}
|
||||||
h
|
h
|
||||||
}
|
}
|
||||||
|
Definition::ExternCrateDecl(extern_crate) => {
|
||||||
|
let mut highlight =
|
||||||
|
Highlight::new(HlTag::Symbol(SymbolKind::Module)) | HlMod::CrateRoot;
|
||||||
|
if extern_crate.alias(db).is_none() {
|
||||||
|
highlight |= HlMod::Library;
|
||||||
|
}
|
||||||
|
highlight
|
||||||
|
}
|
||||||
Definition::Label(_) => Highlight::new(HlTag::Symbol(SymbolKind::Label)),
|
Definition::Label(_) => Highlight::new(HlTag::Symbol(SymbolKind::Label)),
|
||||||
Definition::BuiltinAttr(_) => Highlight::new(HlTag::Symbol(SymbolKind::BuiltinAttr)),
|
Definition::BuiltinAttr(_) => Highlight::new(HlTag::Symbol(SymbolKind::BuiltinAttr)),
|
||||||
Definition::ToolModule(_) => Highlight::new(HlTag::Symbol(SymbolKind::ToolModule)),
|
Definition::ToolModule(_) => Highlight::new(HlTag::Symbol(SymbolKind::ToolModule)),
|
||||||
|
|
|
@ -288,7 +288,7 @@ fn find_doc_string_in_attr(attr: &hir::Attr, it: &ast::Attr) -> Option<ast::Stri
|
||||||
|
|
||||||
fn module_def_to_hl_tag(def: Definition) -> HlTag {
|
fn module_def_to_hl_tag(def: Definition) -> HlTag {
|
||||||
let symbol = match def {
|
let symbol = match def {
|
||||||
Definition::Module(_) => SymbolKind::Module,
|
Definition::Module(_) | Definition::ExternCrateDecl(_) => SymbolKind::Module,
|
||||||
Definition::Function(_) => SymbolKind::Function,
|
Definition::Function(_) => SymbolKind::Function,
|
||||||
Definition::Adt(hir::Adt::Struct(_)) => SymbolKind::Struct,
|
Definition::Adt(hir::Adt::Struct(_)) => SymbolKind::Struct,
|
||||||
Definition::Adt(hir::Adt::Enum(_)) => SymbolKind::Enum,
|
Definition::Adt(hir::Adt::Enum(_)) => SymbolKind::Enum,
|
||||||
|
|
|
@ -44,5 +44,5 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">std</span><span class="semicolon">;</span>
|
<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">std</span><span class="semicolon">;</span>
|
||||||
<span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">alloc</span> <span class="keyword">as</span> <span class="module crate_root default_library declaration library">abc</span><span class="semicolon">;</span>
|
<span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">alloc</span> <span class="keyword">as</span> <span class="module crate_root declaration">abc</span><span class="semicolon">;</span>
|
||||||
</code></pre>
|
</code></pre>
|
|
@ -43,7 +43,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</style>
|
||||||
<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="self_keyword crate_root public">self</span><span class="semicolon">;</span>
|
<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="self_keyword crate_root">self</span><span class="semicolon">;</span>
|
||||||
|
|
||||||
<span class="keyword">use</span> <span class="keyword crate_root public">crate</span><span class="semicolon">;</span>
|
<span class="keyword">use</span> <span class="keyword crate_root public">crate</span><span class="semicolon">;</span>
|
||||||
<span class="keyword">use</span> <span class="self_keyword crate_root public">self</span><span class="semicolon">;</span>
|
<span class="keyword">use</span> <span class="self_keyword crate_root public">self</span><span class="semicolon">;</span>
|
||||||
|
|
|
@ -223,7 +223,8 @@ fn n_attached_trivias<'a>(
|
||||||
) -> usize {
|
) -> usize {
|
||||||
match kind {
|
match kind {
|
||||||
CONST | ENUM | FN | IMPL | MACRO_CALL | MACRO_DEF | MACRO_RULES | MODULE | RECORD_FIELD
|
CONST | ENUM | FN | IMPL | MACRO_CALL | MACRO_DEF | MACRO_RULES | MODULE | RECORD_FIELD
|
||||||
| STATIC | STRUCT | TRAIT | TUPLE_FIELD | TYPE_ALIAS | UNION | USE | VARIANT => {
|
| STATIC | STRUCT | TRAIT | TUPLE_FIELD | TYPE_ALIAS | UNION | USE | VARIANT
|
||||||
|
| EXTERN_CRATE => {
|
||||||
let mut res = 0;
|
let mut res = 0;
|
||||||
let mut trivias = trivias.enumerate().peekable();
|
let mut trivias = trivias.enumerate().peekable();
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,7 @@ impl flags::AnalysisStats {
|
||||||
let mut visited_modules = FxHashSet::default();
|
let mut visited_modules = FxHashSet::default();
|
||||||
let mut visit_queue = Vec::new();
|
let mut visit_queue = Vec::new();
|
||||||
for krate in krates {
|
for krate in krates {
|
||||||
let module = krate.root_module(db);
|
let module = krate.root_module();
|
||||||
let file_id = module.definition_source_file_id(db);
|
let file_id = module.definition_source_file_id(db);
|
||||||
let file_id = file_id.original_file(db);
|
let file_id = file_id.original_file(db);
|
||||||
let source_root = db.file_source_root(file_id);
|
let source_root = db.file_source_root(file_id);
|
||||||
|
|
|
@ -80,7 +80,7 @@ impl flags::Diagnostics {
|
||||||
|
|
||||||
fn all_modules(db: &dyn HirDatabase) -> Vec<Module> {
|
fn all_modules(db: &dyn HirDatabase) -> Vec<Module> {
|
||||||
let mut worklist: Vec<_> =
|
let mut worklist: Vec<_> =
|
||||||
Crate::all(db).into_iter().map(|krate| krate.root_module(db)).collect();
|
Crate::all(db).into_iter().map(|krate| krate.root_module()).collect();
|
||||||
let mut modules = Vec::new();
|
let mut modules = Vec::new();
|
||||||
|
|
||||||
while let Some(module) = worklist.pop() {
|
while let Some(module) = worklist.pop() {
|
||||||
|
|
|
@ -76,7 +76,7 @@ fn all_modules(db: &dyn HirDatabase) -> Vec<Module> {
|
||||||
let mut worklist: Vec<_> = Crate::all(db)
|
let mut worklist: Vec<_> = Crate::all(db)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|x| x.origin(db).is_local())
|
.filter(|x| x.origin(db).is_local())
|
||||||
.map(|krate| krate.root_module(db))
|
.map(|krate| krate.root_module())
|
||||||
.collect();
|
.collect();
|
||||||
let mut modules = Vec::new();
|
let mut modules = Vec::new();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue