Skip to content

Commit 0781832

Browse files
committed
Auto merge of rust-lang#16179 - nicolas-guichard:scip/new_fields, r=Veykril
SCIP: populate new SymbolInformation fields Fixes rust-lang#15919
2 parents d987137 + 73d9c77 commit 0781832

File tree

6 files changed

+498
-318
lines changed

6 files changed

+498
-318
lines changed

crates/ide-db/src/defs.rs

+152-5
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,19 @@
77

88
use arrayvec::ArrayVec;
99
use hir::{
10-
Adt, AsAssocItem, AssocItem, BuiltinAttr, BuiltinType, Const, Crate, DeriveHelper, DocLinkDef,
11-
ExternCrateDecl, Field, Function, GenericParam, HasVisibility, Impl, Label, Local, Macro,
12-
Module, ModuleDef, Name, PathResolution, Semantics, Static, ToolModule, Trait, TraitAlias,
13-
TypeAlias, Variant, Visibility,
10+
Adt, AsAssocItem, AssocItem, AttributeTemplate, BuiltinAttr, BuiltinType, Const, Crate,
11+
DefWithBody, DeriveHelper, DocLinkDef, ExternCrateDecl, Field, Function, GenericParam,
12+
HasVisibility, HirDisplay, Impl, Label, Local, Macro, Module, ModuleDef, Name, PathResolution,
13+
Semantics, Static, ToolModule, Trait, TraitAlias, TypeAlias, Variant, VariantDef, Visibility,
1414
};
15-
use stdx::impl_from;
15+
use stdx::{format_to, impl_from};
1616
use syntax::{
1717
ast::{self, AstNode},
1818
match_ast, SyntaxKind, SyntaxNode, SyntaxToken,
1919
};
2020

21+
use crate::documentation::{Documentation, HasDocs};
22+
use crate::famous_defs::FamousDefs;
2123
use crate::RootDatabase;
2224

2325
// FIXME: a more precise name would probably be `Symbol`?
@@ -83,6 +85,13 @@ impl Definition {
8385
Some(module)
8486
}
8587

88+
pub fn enclosing_definition(&self, db: &RootDatabase) -> Option<Definition> {
89+
match self {
90+
Definition::Local(it) => it.parent(db).try_into().ok(),
91+
_ => None,
92+
}
93+
}
94+
8695
pub fn visibility(&self, db: &RootDatabase) -> Option<Visibility> {
8796
let vis = match self {
8897
Definition::Field(sf) => sf.visibility(db),
@@ -134,6 +143,125 @@ impl Definition {
134143
};
135144
Some(name)
136145
}
146+
147+
pub fn docs(
148+
&self,
149+
db: &RootDatabase,
150+
famous_defs: Option<&FamousDefs<'_, '_>>,
151+
) -> Option<Documentation> {
152+
let docs = match self {
153+
Definition::Macro(it) => it.docs(db),
154+
Definition::Field(it) => it.docs(db),
155+
Definition::Module(it) => it.docs(db),
156+
Definition::Function(it) => it.docs(db),
157+
Definition::Adt(it) => it.docs(db),
158+
Definition::Variant(it) => it.docs(db),
159+
Definition::Const(it) => it.docs(db),
160+
Definition::Static(it) => it.docs(db),
161+
Definition::Trait(it) => it.docs(db),
162+
Definition::TraitAlias(it) => it.docs(db),
163+
Definition::TypeAlias(it) => it.docs(db),
164+
Definition::BuiltinType(it) => {
165+
famous_defs.and_then(|fd| {
166+
// std exposes prim_{} modules with docstrings on the root to document the builtins
167+
let primitive_mod = format!("prim_{}", it.name().display(fd.0.db));
168+
let doc_owner = find_std_module(fd, &primitive_mod)?;
169+
doc_owner.docs(fd.0.db)
170+
})
171+
}
172+
Definition::Local(_) => None,
173+
Definition::SelfType(impl_def) => {
174+
impl_def.self_ty(db).as_adt().map(|adt| adt.docs(db))?
175+
}
176+
Definition::GenericParam(_) => None,
177+
Definition::Label(_) => None,
178+
Definition::ExternCrateDecl(it) => it.docs(db),
179+
180+
Definition::BuiltinAttr(it) => {
181+
let name = it.name(db);
182+
let AttributeTemplate { word, list, name_value_str } = it.template(db)?;
183+
let mut docs = "Valid forms are:".to_owned();
184+
if word {
185+
format_to!(docs, "\n - #\\[{}]", name);
186+
}
187+
if let Some(list) = list {
188+
format_to!(docs, "\n - #\\[{}({})]", name, list);
189+
}
190+
if let Some(name_value_str) = name_value_str {
191+
format_to!(docs, "\n - #\\[{} = {}]", name, name_value_str);
192+
}
193+
Some(Documentation::new(docs.replace('*', "\\*")))
194+
}
195+
Definition::ToolModule(_) => None,
196+
Definition::DeriveHelper(_) => None,
197+
};
198+
199+
docs.or_else(|| {
200+
// docs are missing, for assoc items of trait impls try to fall back to the docs of the
201+
// original item of the trait
202+
let assoc = self.as_assoc_item(db)?;
203+
let trait_ = assoc.containing_trait_impl(db)?;
204+
let name = Some(assoc.name(db)?);
205+
let item = trait_.items(db).into_iter().find(|it| it.name(db) == name)?;
206+
item.docs(db)
207+
})
208+
}
209+
210+
pub fn label(&self, db: &RootDatabase) -> Option<String> {
211+
let label = match *self {
212+
Definition::Macro(it) => it.display(db).to_string(),
213+
Definition::Field(it) => it.display(db).to_string(),
214+
Definition::Module(it) => it.display(db).to_string(),
215+
Definition::Function(it) => it.display(db).to_string(),
216+
Definition::Adt(it) => it.display(db).to_string(),
217+
Definition::Variant(it) => it.display(db).to_string(),
218+
Definition::Const(it) => it.display(db).to_string(),
219+
Definition::Static(it) => it.display(db).to_string(),
220+
Definition::Trait(it) => it.display(db).to_string(),
221+
Definition::TraitAlias(it) => it.display(db).to_string(),
222+
Definition::TypeAlias(it) => it.display(db).to_string(),
223+
Definition::BuiltinType(it) => it.name().display(db).to_string(),
224+
Definition::Local(it) => {
225+
let ty = it.ty(db);
226+
let ty = ty.display_truncated(db, None);
227+
let is_mut = if it.is_mut(db) { "mut " } else { "" };
228+
let desc = match it.primary_source(db).into_ident_pat() {
229+
Some(ident) => {
230+
let name = it.name(db);
231+
let let_kw = if ident.syntax().parent().map_or(false, |p| {
232+
p.kind() == SyntaxKind::LET_STMT || p.kind() == SyntaxKind::LET_EXPR
233+
}) {
234+
"let "
235+
} else {
236+
""
237+
};
238+
format!("{let_kw}{is_mut}{}: {ty}", name.display(db))
239+
}
240+
None => format!("{is_mut}self: {ty}"),
241+
};
242+
desc
243+
}
244+
Definition::SelfType(impl_def) => {
245+
impl_def.self_ty(db).as_adt().and_then(|adt| Definition::Adt(adt).label(db))?
246+
}
247+
Definition::GenericParam(it) => it.display(db).to_string(),
248+
Definition::Label(it) => it.name(db).display(db).to_string(),
249+
Definition::ExternCrateDecl(it) => it.display(db).to_string(),
250+
Definition::BuiltinAttr(it) => format!("#[{}]", it.name(db)),
251+
Definition::ToolModule(it) => it.name(db).to_string(),
252+
Definition::DeriveHelper(it) => format!("derive_helper {}", it.name(db).display(db)),
253+
};
254+
Some(label)
255+
}
256+
}
257+
258+
fn find_std_module(famous_defs: &FamousDefs<'_, '_>, name: &str) -> Option<hir::Module> {
259+
let db = famous_defs.0.db;
260+
let std_crate = famous_defs.std()?;
261+
let std_root_module = std_crate.root_module();
262+
std_root_module.children(db).find(|module| {
263+
module.name(db).map_or(false, |module| module.display(db).to_string() == name)
264+
})
137265
}
138266

139267
// FIXME: IdentClass as a name no longer fits
@@ -662,3 +790,22 @@ impl From<DocLinkDef> for Definition {
662790
}
663791
}
664792
}
793+
794+
impl From<VariantDef> for Definition {
795+
fn from(def: VariantDef) -> Self {
796+
ModuleDef::from(def).into()
797+
}
798+
}
799+
800+
impl TryFrom<DefWithBody> for Definition {
801+
type Error = ();
802+
fn try_from(def: DefWithBody) -> Result<Self, Self::Error> {
803+
match def {
804+
DefWithBody::Function(it) => Ok(it.into()),
805+
DefWithBody::Static(it) => Ok(it.into()),
806+
DefWithBody::Const(it) => Ok(it.into()),
807+
DefWithBody::Variant(it) => Ok(it.into()),
808+
DefWithBody::InTypeConst(_) => Err(()),
809+
}
810+
}
811+
}

0 commit comments

Comments
 (0)