use std::sync::Arc;
use cairo_lang_defs::ids::{LanguageElementId, UseId};
use cairo_lang_diagnostics::{Diagnostics, Maybe, ToMaybe};
use cairo_lang_proc_macros::DebugWithDb;
use cairo_lang_utils::Upcast;
use crate::db::SemanticGroup;
use crate::diagnostic::SemanticDiagnosticKind::*;
use crate::diagnostic::{NotFoundItemType, SemanticDiagnostics};
use crate::resolve::{ResolvedGenericItem, ResolvedItems, Resolver};
use crate::SemanticDiagnostic;
#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
#[debug_db(dyn SemanticGroup + 'static)]
pub struct UseData {
diagnostics: Diagnostics<SemanticDiagnostic>,
resolved_item: Maybe<ResolvedGenericItem>,
resolved_lookback: Arc<ResolvedItems>,
}
pub fn priv_use_semantic_data(db: &(dyn SemanticGroup), use_id: UseId) -> Maybe<UseData> {
let module_file_id = use_id.module_file_id(db.upcast());
let mut diagnostics = SemanticDiagnostics::new(module_file_id);
let mut resolver = Resolver::new(db, module_file_id);
let module_uses = db.module_uses(module_file_id.0)?;
let use_ast = module_uses.get(&use_id).to_maybe()?;
let syntax_db = db.upcast();
let resolved_item = resolver.resolve_generic_path(
&mut diagnostics,
&use_ast.name(syntax_db),
NotFoundItemType::Identifier,
);
let resolved_lookback = Arc::new(resolver.resolved_items);
Ok(UseData { diagnostics: diagnostics.build(), resolved_item, resolved_lookback })
}
pub fn priv_use_semantic_data_cycle(
db: &dyn SemanticGroup,
cycle: &[String],
use_id: &UseId,
) -> Maybe<UseData> {
let module_file_id = use_id.module_file_id(db.upcast());
let mut diagnostics = SemanticDiagnostics::new(module_file_id);
let module_uses = db.module_uses(module_file_id.0)?;
let use_ast = module_uses.get(use_id).to_maybe()?;
let syntax_db = db.upcast();
let err = Err(diagnostics.report(
&use_ast.name(syntax_db),
if cycle.len() == 1 {
PathNotFound(NotFoundItemType::Identifier)
} else {
UseCycle
},
));
Ok(UseData {
diagnostics: diagnostics.build(),
resolved_item: err,
resolved_lookback: Arc::new(ResolvedItems::default()),
})
}
pub fn use_semantic_diagnostics(
db: &dyn SemanticGroup,
use_id: UseId,
) -> Diagnostics<SemanticDiagnostic> {
db.priv_use_semantic_data(use_id).map(|data| data.diagnostics).unwrap_or_default()
}
pub fn use_resolved_lookback(db: &dyn SemanticGroup, use_id: UseId) -> Maybe<Arc<ResolvedItems>> {
Ok(db.priv_use_semantic_data(use_id)?.resolved_lookback)
}
pub trait SemanticUseEx<'a>: Upcast<dyn SemanticGroup + 'a> {
fn use_resolved_item(&self, use_id: UseId) -> Maybe<ResolvedGenericItem> {
let db = self.upcast();
db.priv_use_semantic_data(use_id)?.resolved_item
}
}
impl<'a, T: Upcast<dyn SemanticGroup + 'a> + ?Sized> SemanticUseEx<'a> for T {}