attr::Attrs,
body::Expander,
db::DefDatabase,
- item_tree::{AssocItem, ItemTreeId, ModItem},
+ item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param},
type_ref::{TypeBound, TypeRef},
visibility::RawVisibility,
AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId,
/// True if the first param is `self`. This is relevant to decide whether this
/// can be called as a method.
pub has_self_param: bool,
- pub is_unsafe: bool,
+ pub has_body: bool,
+ pub qualifier: FunctionQualifier,
+ pub is_in_extern_block: bool,
pub is_varargs: bool,
pub visibility: RawVisibility,
}
impl FunctionData {
pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc<FunctionData> {
let loc = func.lookup(db);
+ let krate = loc.container.module(db).krate;
+ let crate_graph = db.crate_graph();
+ let cfg_options = &crate_graph[krate].cfg_options;
let item_tree = db.item_tree(loc.id.file_id);
let func = &item_tree[loc.id.value];
+ let enabled_params = func
+ .params
+ .clone()
+ .filter(|¶m| item_tree.attrs(db, krate, param.into()).is_cfg_enabled(cfg_options));
+
+ // If last cfg-enabled param is a `...` param, it's a varargs function.
+ let is_varargs = enabled_params
+ .clone()
+ .next_back()
+ .map_or(false, |param| matches!(item_tree[param], Param::Varargs));
+
Arc::new(FunctionData {
name: func.name.clone(),
- params: func.params.to_vec(),
- ret_type: func.ret_type.clone(),
- attrs: item_tree.attrs(ModItem::from(loc.id.value).into()).clone(),
+ params: enabled_params
+ .clone()
+ .filter_map(|id| match &item_tree[id] {
+ Param::Normal(ty) => Some(item_tree[*ty].clone()),
+ Param::Varargs => None,
+ })
+ .collect(),
+ ret_type: item_tree[func.ret_type].clone(),
+ attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
has_self_param: func.has_self_param,
- is_unsafe: func.is_unsafe,
- is_varargs: func.is_varargs,
+ has_body: func.has_body,
+ qualifier: func.qualifier.clone(),
+ is_in_extern_block: func.is_in_extern_block,
+ is_varargs,
visibility: item_tree[func.visibility].clone(),
})
}
Arc::new(TypeAliasData {
name: typ.name.clone(),
- type_ref: typ.type_ref.clone(),
+ type_ref: typ.type_ref.map(|id| item_tree[id].clone()),
visibility: item_tree[typ.visibility].clone(),
is_extern: typ.is_extern,
bounds: typ.bounds.to_vec(),
pub struct TraitData {
pub name: Name,
pub items: Vec<(Name, AssocItemId)>,
- pub auto: bool,
+ pub is_auto: bool,
+ pub is_unsafe: bool,
+ pub visibility: RawVisibility,
+ pub bounds: Box<[TypeBound]>,
}
impl TraitData {
let item_tree = db.item_tree(tr_loc.id.file_id);
let tr_def = &item_tree[tr_loc.id.value];
let name = tr_def.name.clone();
- let auto = tr_def.auto;
- let module_id = tr_loc.container.module(db);
+ let is_auto = tr_def.is_auto;
+ let is_unsafe = tr_def.is_unsafe;
+ let module_id = tr_loc.container;
let container = AssocContainerId::TraitId(tr);
let mut expander = Expander::new(db, tr_loc.id.file_id, module_id);
+ let visibility = item_tree[tr_def.visibility].clone();
+ let bounds = tr_def.bounds.clone();
let items = collect_items(
db,
100,
);
- Arc::new(TraitData { name, items, auto })
+ Arc::new(TraitData { name, items, is_auto, is_unsafe, visibility, bounds })
}
pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
let item_tree = db.item_tree(impl_loc.id.file_id);
let impl_def = &item_tree[impl_loc.id.value];
- let target_trait = impl_def.target_trait.clone();
- let target_type = impl_def.target_type.clone();
+ let target_trait = impl_def.target_trait.map(|id| item_tree[id].clone());
+ let target_type = item_tree[impl_def.target_type].clone();
let is_negative = impl_def.is_negative;
- let module_id = impl_loc.container.module(db);
+ let module_id = impl_loc.container;
let container = AssocContainerId::ImplId(id);
let mut expander = Expander::new(db, impl_loc.id.file_id, module_id);
Arc::new(ConstData {
name: konst.name.clone(),
- type_ref: konst.type_ref.clone(),
+ type_ref: item_tree[konst.type_ref].clone(),
visibility: item_tree[konst.visibility].clone(),
})
}
pub type_ref: TypeRef,
pub visibility: RawVisibility,
pub mutable: bool,
+ pub is_extern: bool,
}
impl StaticData {
Arc::new(StaticData {
name: Some(statik.name.clone()),
- type_ref: statik.type_ref.clone(),
+ type_ref: item_tree[statik.type_ref].clone(),
visibility: item_tree[statik.visibility].clone(),
mutable: statik.mutable,
+ is_extern: statik.is_extern,
})
}
}
let mut items = Vec::new();
for item in assoc_items {
+ let attrs = item_tree.attrs(db, module.krate, ModItem::from(item).into());
+ if !attrs.is_cfg_enabled(&cfg_options) {
+ continue;
+ }
+
match item {
AssocItem::Function(id) => {
let item = &item_tree[id];
- let attrs = item_tree.attrs(ModItem::from(id).into());
- if !attrs.is_cfg_enabled(&cfg_options) {
- continue;
- }
let def = FunctionLoc { container, id: ItemTreeId::new(file_id, id) }.intern(db);
items.push((item.name.clone(), def.into()));
}
- // FIXME: cfg?
AssocItem::Const(id) => {
let item = &item_tree[id];
let name = match item.name.clone() {
let ast_id_map = db.ast_id_map(file_id);
let root = db.parse_or_expand(file_id).unwrap();
let call = ast_id_map.get(call.ast_id).to_node(&root);
-
- if let Some((mark, mac)) = expander.enter_expand(db, None, call) {
- let src: InFile<ast::MacroItems> = expander.to_source(mac);
- let item_tree = db.item_tree(src.file_id);
- let iter =
- item_tree.top_level_items().iter().filter_map(ModItem::as_assoc_item);
- items.extend(collect_items(
- db,
- module,
- expander,
- iter,
- src.file_id,
- container,
- limit - 1,
- ));
-
- expander.exit(db, mark);
+ let res = expander.enter_expand(db, call);
+
+ if let Ok(res) = res {
+ if let Some((mark, mac)) = res.value {
+ let src: InFile<ast::MacroItems> = expander.to_source(mac);
+ let item_tree = db.item_tree(src.file_id);
+ let iter =
+ item_tree.top_level_items().iter().filter_map(ModItem::as_assoc_item);
+ items.extend(collect_items(
+ db,
+ module,
+ expander,
+ iter,
+ src.file_id,
+ container,
+ limit - 1,
+ ));
+
+ expander.exit(db, mark);
+ }
}
}
}