use std::iter;
use cairo_lang_defs::ids::{
LanguageElementId, LookupItemId, ModuleItemId, NamedLanguageElementId,
TopLevelLanguageElementId, TraitItemId,
};
use cairo_lang_doc::db::DocGroup;
use cairo_lang_syntax::node::SyntaxNode;
use cairo_lang_syntax::node::ids::SyntaxStablePtrId;
use itertools::Itertools;
use crate::lang::db::{AnalysisDatabase, LsSemanticGroup};
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct ItemDef<'db> {
lookup_item_id: LookupItemId<'db>,
context_items: Vec<LookupItemId<'db>>,
definition_stable_ptr: SyntaxStablePtrId<'db>,
}
impl<'db> ItemDef<'db> {
pub(super) fn new(db: &'db AnalysisDatabase, definition_node: SyntaxNode<'db>) -> Option<Self> {
let lookup_item_ids = db.collect_lookup_items_with_parent_files(definition_node)?;
let mut lookup_item_ids_iter = lookup_item_ids.iter();
let lookup_item_id = *lookup_item_ids_iter.next()?;
let context_items = lookup_item_ids_iter
.take_while(|item| {
matches!(
item,
LookupItemId::ModuleItem(ModuleItemId::Struct(_))
| LookupItemId::ModuleItem(ModuleItemId::Enum(_))
| LookupItemId::ModuleItem(ModuleItemId::Trait(_))
| LookupItemId::ModuleItem(ModuleItemId::Impl(_))
| LookupItemId::TraitItem(TraitItemId::Impl(_))
)
})
.copied()
.collect();
Some(Self {
lookup_item_id,
context_items,
definition_stable_ptr: definition_node.stable_ptr(db),
})
}
pub fn definition_stable_ptr(&self) -> SyntaxStablePtrId<'db> {
self.definition_stable_ptr
}
pub fn signature(&self, db: &'db AnalysisDatabase) -> String {
let contexts = self.context_items.iter().copied().rev();
let this = iter::once(self.lookup_item_id);
contexts.chain(this).filter_map(|item| db.get_item_signature(item.into())).join("\n")
}
pub fn signature_with_text(&self, db: &'db AnalysisDatabase, text: &str) -> String {
let this = db.get_item_signature(self.lookup_item_id.into()).unwrap_or_else(|| "".into());
let contexts = self.context_items.iter().copied().rev();
let contexts = contexts.filter_map(|item| db.get_item_signature(item.into())).join("\n");
format!("{this}{text}{contexts}")
}
pub fn documentation(&self, db: &'db AnalysisDatabase) -> Option<String> {
db.get_item_documentation(self.lookup_item_id.into())
}
pub fn definition_path(&self, db: &'db AnalysisDatabase) -> String {
match self.lookup_item_id {
LookupItemId::ModuleItem(item) => item.parent_module(db).full_path(db),
LookupItemId::TraitItem(item) => item.trait_id(db).full_path(db),
LookupItemId::ImplItem(item) => item.impl_def_id(db).full_path(db),
}
}
pub fn name(&self, db: &'db AnalysisDatabase) -> String {
match self.lookup_item_id {
LookupItemId::ModuleItem(item) => item.name(db).to_string(db),
LookupItemId::TraitItem(item) => item.name(db).to_string(db),
LookupItemId::ImplItem(item) => item.name(db).to_string(db),
}
}
}