cairo_lang_semantic/items/
attribute.rs

1use cairo_lang_defs::ids::{
2    EnumId, ExternTypeId, FreeFunctionId, FunctionWithBodyId, ImplAliasId, ImplDefId,
3    ImplFunctionId, ImplTypeDefId, ModuleId, StructId, SubmoduleId, TraitFunctionId, TraitId,
4    TraitTypeId,
5};
6use cairo_lang_diagnostics::Maybe;
7use cairo_lang_syntax::attribute::structured::Attribute;
8
9use crate::db::SemanticGroup;
10use crate::{ConcreteEnumId, ConcreteExternTypeId, ConcreteStructId};
11
12pub trait AttributeTrait {
13    fn name(&self, db: &dyn SemanticGroup) -> String;
14    fn args(&self, db: &dyn SemanticGroup) -> String;
15    fn full_text(&self, db: &dyn SemanticGroup) -> String {
16        if self.args(db).is_empty() {
17            self.name(db)
18        } else {
19            format!("{}({})", self.name(db), self.args(db))
20        }
21    }
22    fn format(&self, db: &dyn SemanticGroup) -> String {
23        format!("#[{}]", self.full_text(db))
24    }
25}
26impl AttributeTrait for Attribute {
27    fn name(&self, _db: &dyn SemanticGroup) -> String {
28        self.id.to_string()
29    }
30    fn args(&self, db: &dyn SemanticGroup) -> String {
31        self.args.iter().map(|arg| arg.text(db.upcast())).collect::<Vec<_>>().join(", ")
32    }
33}
34
35/// Trait for querying attributes of semantic items.
36pub trait SemanticQueryAttrs {
37    /// Get the list of attributes attached to this node.
38    ///
39    /// Implementation detail, should not be used by this trait users.
40    #[doc(hidden)]
41    fn attributes_elements(&self, db: &dyn SemanticGroup) -> Maybe<Vec<Attribute>>;
42
43    /// Collect all attributes attached to this node whose name (without args) is exactly `attr`.
44    fn query_attr(&self, db: &dyn SemanticGroup, attr: &str) -> Maybe<Vec<Attribute>> {
45        Ok(self.attributes_elements(db)?.into_iter().filter(|a| a.name(db) == attr).collect())
46    }
47
48    /// Find first attribute attached to this node whose name (without args) is exactly `attr`.
49    fn find_attr(&self, db: &dyn SemanticGroup, attr: &str) -> Maybe<Option<Attribute>> {
50        Ok(self.query_attr(db, attr)?.into_iter().next())
51    }
52
53    /// Check if this node has an attribute whose name (without args) is exactly `attr`.
54    fn has_attr(&self, db: &dyn SemanticGroup, attr: &str) -> Maybe<bool> {
55        Ok(self.find_attr(db, attr)?.is_some())
56    }
57
58    /// Checks if the given object has an attribute with the given name and argument.
59    fn has_attr_with_arg(
60        &self,
61        db: &dyn SemanticGroup,
62        attr_name: &str,
63        arg_name: &str,
64    ) -> Maybe<bool> {
65        Ok(self
66            .query_attr(db, attr_name)?
67            .iter()
68            .any(|attr| attr.is_single_unnamed_arg(db.upcast(), arg_name)))
69    }
70}
71
72impl SemanticQueryAttrs for ModuleId {
73    fn attributes_elements(&self, db: &dyn SemanticGroup) -> Maybe<Vec<Attribute>> {
74        db.module_attributes(*self)
75    }
76}
77impl SemanticQueryAttrs for StructId {
78    fn attributes_elements(&self, db: &dyn SemanticGroup) -> Maybe<Vec<Attribute>> {
79        db.struct_attributes(*self)
80    }
81}
82impl SemanticQueryAttrs for ConcreteStructId {
83    fn attributes_elements(&self, db: &dyn SemanticGroup) -> Maybe<Vec<Attribute>> {
84        self.struct_id(db).attributes_elements(db)
85    }
86}
87impl SemanticQueryAttrs for TraitId {
88    fn attributes_elements(&self, db: &dyn SemanticGroup) -> Maybe<Vec<Attribute>> {
89        db.trait_attributes(*self)
90    }
91}
92impl SemanticQueryAttrs for FunctionWithBodyId {
93    fn attributes_elements(&self, db: &dyn SemanticGroup) -> Maybe<Vec<Attribute>> {
94        db.function_with_body_attributes(*self)
95    }
96}
97impl SemanticQueryAttrs for ImplDefId {
98    fn attributes_elements(&self, db: &dyn SemanticGroup) -> Maybe<Vec<Attribute>> {
99        db.impl_def_attributes(*self)
100    }
101}
102impl SemanticQueryAttrs for ImplAliasId {
103    fn attributes_elements(&self, db: &dyn SemanticGroup) -> Maybe<Vec<Attribute>> {
104        db.impl_alias_attributes(*self)
105    }
106}
107impl SemanticQueryAttrs for EnumId {
108    fn attributes_elements(&self, db: &dyn SemanticGroup) -> Maybe<Vec<Attribute>> {
109        db.enum_attributes(*self)
110    }
111}
112impl SemanticQueryAttrs for ConcreteEnumId {
113    fn attributes_elements(&self, db: &dyn SemanticGroup) -> Maybe<Vec<Attribute>> {
114        self.enum_id(db).attributes_elements(db)
115    }
116}
117impl SemanticQueryAttrs for ExternTypeId {
118    fn attributes_elements(&self, db: &dyn SemanticGroup) -> Maybe<Vec<Attribute>> {
119        db.extern_type_attributes(*self)
120    }
121}
122impl SemanticQueryAttrs for ConcreteExternTypeId {
123    fn attributes_elements(&self, db: &dyn SemanticGroup) -> Maybe<Vec<Attribute>> {
124        self.extern_type_id(db).attributes_elements(db)
125    }
126}
127impl SemanticQueryAttrs for SubmoduleId {
128    fn attributes_elements(&self, db: &dyn SemanticGroup) -> Maybe<Vec<Attribute>> {
129        ModuleId::Submodule(*self).attributes_elements(db)
130    }
131}
132impl SemanticQueryAttrs for FreeFunctionId {
133    fn attributes_elements(&self, db: &dyn SemanticGroup) -> Maybe<Vec<Attribute>> {
134        FunctionWithBodyId::Free(*self).attributes_elements(db)
135    }
136}
137
138impl SemanticQueryAttrs for TraitTypeId {
139    fn attributes_elements(&self, db: &dyn SemanticGroup) -> Maybe<Vec<Attribute>> {
140        db.trait_type_attributes(*self)
141    }
142}
143impl SemanticQueryAttrs for TraitFunctionId {
144    fn attributes_elements(&self, db: &dyn SemanticGroup) -> Maybe<Vec<Attribute>> {
145        db.trait_function_attributes(*self)
146    }
147}
148
149impl SemanticQueryAttrs for ImplTypeDefId {
150    fn attributes_elements(&self, db: &dyn SemanticGroup) -> Maybe<Vec<Attribute>> {
151        db.impl_type_def_attributes(*self)
152    }
153}
154impl SemanticQueryAttrs for ImplFunctionId {
155    fn attributes_elements(&self, db: &dyn SemanticGroup) -> Maybe<Vec<Attribute>> {
156        db.impl_function_attributes(*self)
157    }
158}