pub mod type_ref;
pub mod builtin_type;
pub mod builtin_attr;
-pub mod diagnostics;
pub mod per_ns;
pub mod item_scope;
sync::Arc,
};
+use attr::Attr;
use base_db::{impl_intern_key, salsa, CrateId};
use hir_expand::{
ast_id_map::FileAstId,
eager::{expand_eager_macro, ErrorEmitted, ErrorSink},
hygiene::Hygiene,
- AstId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
+ AstId, FragmentKind, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
};
use la_arena::Idx;
use nameres::DefMap;
+use path::ModPath;
+use stdx::impl_from;
use syntax::ast;
-use crate::builtin_type::BuiltinType;
-use item_tree::{
- Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, ModItem, Static, Struct, Trait,
- TypeAlias, Union,
+use crate::{
+ adt::VariantData,
+ attr::AttrId,
+ builtin_type::BuiltinType,
+ item_tree::{
+ Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, ModItem, Static, Struct, Trait,
+ TypeAlias, Union,
+ },
};
-use stdx::impl_from;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ModuleId {
pub fn containing_module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> {
self.def_map(db).containing_module(self.local_id)
}
+
+ pub fn containing_block(&self) -> Option<BlockId> {
+ self.block
+ }
+
+ /// Returns `true` if this module represents a block expression.
+ ///
+ /// Returns `false` if this module is a submodule *inside* a block expression
+ /// (eg. `m` in `{ mod m {} }`).
+ pub fn is_block_root(&self, db: &dyn db::DefDatabase) -> bool {
+ if self.block.is_none() {
+ return false;
+ }
+
+ self.def_map(db)[self.local_id].parent.is_none()
+ }
}
/// An ID of a module, **local** to a specific crate
for AttrDefId
);
+impl From<AssocContainerId> for AttrDefId {
+ fn from(acid: AssocContainerId) -> Self {
+ match acid {
+ AssocContainerId::ModuleId(mid) => AttrDefId::ModuleId(mid),
+ AssocContainerId::ImplId(iid) => AttrDefId::ImplId(iid),
+ AssocContainerId::TraitId(tid) => AttrDefId::TraitId(tid),
+ }
+ }
+}
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum VariantId {
EnumVariantId(EnumVariantId),
}
impl_from!(EnumVariantId, StructId, UnionId for VariantId);
+impl VariantId {
+ pub fn variant_data(self, db: &dyn db::DefDatabase) -> Arc<VariantData> {
+ match self {
+ VariantId::StructId(it) => db.struct_data(it).variant_data.clone(),
+ VariantId::UnionId(it) => db.union_data(it).variant_data.clone(),
+ VariantId::EnumVariantId(it) => {
+ db.enum_data(it.parent).variants[it.local_id].variant_data.clone()
+ }
+ }
+ }
+
+ pub fn file_id(self, db: &dyn db::DefDatabase) -> HirFileId {
+ match self {
+ VariantId::EnumVariantId(it) => it.parent.lookup(db).id.file_id(),
+ VariantId::StructId(it) => it.lookup(db).id.file_id(),
+ VariantId::UnionId(it) => it.lookup(db).id.file_id(),
+ }
+ }
+
+ pub fn adt_id(self) -> AdtId {
+ match self {
+ VariantId::EnumVariantId(it) => it.parent.into(),
+ VariantId::StructId(it) => it.into(),
+ VariantId::UnionId(it) => it.into(),
+ }
+ }
+}
+
trait Intern {
type ID;
fn intern(self, db: &dyn db::DefDatabase) -> Self::ID;
}
}
+impl HasModule for TypeAliasId {
+ fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
+ self.lookup(db).module(db)
+ }
+}
+
+impl HasModule for TraitId {
+ fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
+ self.lookup(db).container
+ }
+}
+
impl HasModule for StaticLoc {
fn module(&self, _db: &dyn db::DefDatabase) -> ModuleId {
self.container
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
mut error_sink: &mut dyn FnMut(mbe::ExpandError),
) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
+ let fragment = hir_expand::to_fragment_kind(self.value);
let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
let h = Hygiene::new(db.upcast(), self.file_id);
- let path = self.value.path().and_then(|path| path::ModPath::from_src(path, &h));
+ let path = self.value.path().and_then(|path| path::ModPath::from_src(db, path, &h));
let path = match error_sink
.option(path, || mbe::ExpandError::Other("malformed macro invocation".into()))
macro_call_as_call_id(
&AstIdWithPath::new(ast_id.file_id, ast_id.value, path),
+ fragment,
db,
krate,
resolver,
}
}
-pub struct UnresolvedMacro;
+#[derive(Debug)]
+pub struct UnresolvedMacro {
+ pub path: ModPath,
+}
fn macro_call_as_call_id(
call: &AstIdWithPath<ast::MacroCall>,
+ fragment: FragmentKind,
db: &dyn db::DefDatabase,
krate: CrateId,
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
error_sink: &mut dyn FnMut(mbe::ExpandError),
) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
- let def: MacroDefId = resolver(call.path.clone()).ok_or(UnresolvedMacro)?;
+ let def: MacroDefId =
+ resolver(call.path.clone()).ok_or_else(|| UnresolvedMacro { path: call.path.clone() })?;
let res = if let MacroDefKind::BuiltInEager(..) = def.kind {
let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db.upcast()));
krate,
macro_call,
def,
- &|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?),
+ &|path: ast::Path| resolver(path::ModPath::from_src(db, path, &hygiene)?),
error_sink,
)
.map(MacroCallId::from)
} else {
- Ok(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(call.ast_id)).into())
+ Ok(def.as_lazy_macro(
+ db.upcast(),
+ krate,
+ MacroCallKind::FnLike { ast_id: call.ast_id, fragment },
+ ))
};
Ok(res)
}
fn derive_macro_as_call_id(
item_attr: &AstIdWithPath<ast::Item>,
+ derive_attr: AttrId,
db: &dyn db::DefDatabase,
krate: CrateId,
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
) -> Result<MacroCallId, UnresolvedMacro> {
- let def: MacroDefId = resolver(item_attr.path.clone()).ok_or(UnresolvedMacro)?;
- let last_segment = item_attr.path.segments().last().ok_or(UnresolvedMacro)?;
- let res = def
- .as_lazy_macro(
- db.upcast(),
- krate,
- MacroCallKind::Derive(item_attr.ast_id, last_segment.to_string()),
- )
- .into();
+ let def: MacroDefId = resolver(item_attr.path.clone())
+ .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?;
+ let last_segment = item_attr
+ .path
+ .segments()
+ .last()
+ .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?;
+ let res = def.as_lazy_macro(
+ db.upcast(),
+ krate,
+ MacroCallKind::Derive {
+ ast_id: item_attr.ast_id,
+ derive_name: last_segment.to_string(),
+ derive_attr_index: derive_attr.ast_index,
+ },
+ );
+ Ok(res)
+}
+
+fn attr_macro_as_call_id(
+ item_attr: &AstIdWithPath<ast::Item>,
+ macro_attr: &Attr,
+ db: &dyn db::DefDatabase,
+ krate: CrateId,
+ resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
+) -> Result<MacroCallId, UnresolvedMacro> {
+ let def: MacroDefId = resolver(item_attr.path.clone())
+ .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?;
+ let last_segment = item_attr
+ .path
+ .segments()
+ .last()
+ .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?;
+ let mut arg = match ¯o_attr.input {
+ Some(input) => match &**input {
+ attr::AttrInput::Literal(_) => tt::Subtree::default(),
+ attr::AttrInput::TokenTree(tt) => tt.clone(),
+ },
+ None => tt::Subtree::default(),
+ };
+ // The parentheses are always disposed here.
+ arg.delimiter = None;
+
+ let res = def.as_lazy_macro(
+ db.upcast(),
+ krate,
+ MacroCallKind::Attr {
+ ast_id: item_attr.ast_id,
+ attr_name: last_segment.to_string(),
+ attr_args: arg,
+ invoc_attr_index: macro_attr.id.ast_index,
+ },
+ );
Ok(res)
}