//! FIXME: write short doc here use std::{ hash::{Hash, Hasher}, sync::Arc, }; pub use hir_def::ast_id_map::{AstIdMap, ErasedFileAstId, FileAstId}; use ra_syntax::{AstNode, SyntaxNode}; use crate::{db::AstDatabase, HirFileId}; /// `AstId` points to an AST node in any file. /// /// It is stable across reparses, and can be used as salsa key/value. // FIXME: isn't this just a `Source>` ? #[derive(Debug)] pub(crate) struct AstId { file_id: HirFileId, file_ast_id: FileAstId, } impl Clone for AstId { fn clone(&self) -> AstId { *self } } impl Copy for AstId {} impl PartialEq for AstId { fn eq(&self, other: &Self) -> bool { (self.file_id, self.file_ast_id) == (other.file_id, other.file_ast_id) } } impl Eq for AstId {} impl Hash for AstId { fn hash(&self, hasher: &mut H) { (self.file_id, self.file_ast_id).hash(hasher); } } impl AstId { pub fn new(file_id: HirFileId, file_ast_id: FileAstId) -> AstId { AstId { file_id, file_ast_id } } pub(crate) fn file_id(&self) -> HirFileId { self.file_id } pub(crate) fn to_node(&self, db: &impl AstDatabase) -> N { let syntax_node = db.ast_id_to_node(self.file_id, self.file_ast_id.into()); N::cast(syntax_node).unwrap() } } pub(crate) fn ast_id_map_query(db: &impl AstDatabase, file_id: HirFileId) -> Arc { let map = if let Some(node) = db.parse_or_expand(file_id) { AstIdMap::from_source(&node) } else { AstIdMap::default() }; Arc::new(map) } pub(crate) fn file_item_query( db: &impl AstDatabase, file_id: HirFileId, ast_id: ErasedFileAstId, ) -> SyntaxNode { let node = db.parse_or_expand(file_id).unwrap(); db.ast_id_map(file_id)[ast_id].to_node(&node) }