cairo_lang_semantic/items/
attribute.rs1use 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_filesystem::ids::SmolStrId;
8use cairo_lang_syntax::attribute::structured::Attribute;
9use salsa::Database;
10
11use crate::items::enm::EnumSemantic;
12use crate::items::extern_type::ExternTypeSemantic;
13use crate::items::function_with_body::FunctionWithBodySemantic;
14use crate::items::imp::ImplSemantic;
15use crate::items::impl_alias::ImplAliasSemantic;
16use crate::items::module::ModuleSemantic;
17use crate::items::structure::StructSemantic;
18use crate::items::trt::TraitSemantic;
19use crate::{ConcreteEnumId, ConcreteExternTypeId, ConcreteStructId};
20
21pub trait AttributeTrait<'db> {
22 fn name(&self, db: &'db dyn Database) -> SmolStrId<'db>;
23 fn args(&self, db: &dyn Database) -> String;
24 fn full_text(&self, db: &'db dyn Database) -> String {
25 if self.args(db).is_empty() {
26 self.name(db).to_string(db)
27 } else {
28 format!("{}({})", self.name(db).long(db), self.args(db))
29 }
30 }
31 fn format(&self, db: &'db dyn Database) -> String {
32 format!("#[{}]", self.full_text(db))
33 }
34}
35impl<'db> AttributeTrait<'db> for Attribute<'db> {
36 fn name(&self, _db: &'db dyn Database) -> SmolStrId<'db> {
37 self.id
38 }
39 fn args(&self, db: &dyn Database) -> String {
40 self.args.iter().map(|arg| arg.text(db)).collect::<Vec<_>>().join(", ")
41 }
42}
43
44pub trait SemanticQueryAttrs<'db> {
46 #[doc(hidden)]
50 fn attributes_elements(&self, db: &'db dyn Database) -> Maybe<&'db [Attribute<'db>]>;
51
52 fn query_attr(
54 &self,
55 db: &'db dyn Database,
56 attr: &str,
57 ) -> Maybe<impl Iterator<Item = &'db Attribute<'db>>> {
58 Ok(self.attributes_elements(db)?.iter().filter(move |a| a.id.long(db) == attr))
59 }
60
61 fn find_attr(&self, db: &'db dyn Database, attr: &str) -> Maybe<Option<&'db Attribute<'db>>> {
63 Ok(self.query_attr(db, attr)?.next())
64 }
65
66 fn has_attr(&self, db: &'db dyn Database, attr: &str) -> Maybe<bool> {
68 Ok(self.find_attr(db, attr)?.is_some())
69 }
70
71 fn has_attr_with_arg(
73 &self,
74 db: &'db dyn Database,
75 attr_name: &str,
76 arg_name: &str,
77 ) -> Maybe<bool> {
78 Ok(self.query_attr(db, attr_name)?.any(|attr| attr.is_single_unnamed_arg(db, arg_name)))
79 }
80}
81
82impl<'db> SemanticQueryAttrs<'db> for ModuleId<'db> {
83 fn attributes_elements(&self, db: &'db dyn Database) -> Maybe<&'db [Attribute<'db>]> {
84 db.module_attributes(*self)
85 }
86}
87impl<'db> SemanticQueryAttrs<'db> for StructId<'db> {
88 fn attributes_elements(&self, db: &'db dyn Database) -> Maybe<&'db [Attribute<'db>]> {
89 db.struct_attributes(*self)
90 }
91}
92impl<'db> SemanticQueryAttrs<'db> for ConcreteStructId<'db> {
93 fn attributes_elements(&self, db: &'db dyn Database) -> Maybe<&'db [Attribute<'db>]> {
94 self.struct_id(db).attributes_elements(db)
95 }
96}
97impl<'db> SemanticQueryAttrs<'db> for TraitId<'db> {
98 fn attributes_elements(&self, db: &'db dyn Database) -> Maybe<&'db [Attribute<'db>]> {
99 db.trait_attributes(*self)
100 }
101}
102impl<'db> SemanticQueryAttrs<'db> for FunctionWithBodyId<'db> {
103 fn attributes_elements(&self, db: &'db dyn Database) -> Maybe<&'db [Attribute<'db>]> {
104 db.function_with_body_attributes(*self)
105 }
106}
107impl<'db> SemanticQueryAttrs<'db> for ImplDefId<'db> {
108 fn attributes_elements(&self, db: &'db dyn Database) -> Maybe<&'db [Attribute<'db>]> {
109 db.impl_def_attributes(*self)
110 }
111}
112impl<'db> SemanticQueryAttrs<'db> for ImplAliasId<'db> {
113 fn attributes_elements(&self, db: &'db dyn Database) -> Maybe<&'db [Attribute<'db>]> {
114 db.impl_alias_attributes(*self)
115 }
116}
117impl<'db> SemanticQueryAttrs<'db> for EnumId<'db> {
118 fn attributes_elements(&self, db: &'db dyn Database) -> Maybe<&'db [Attribute<'db>]> {
119 db.enum_attributes(*self)
120 }
121}
122impl<'db> SemanticQueryAttrs<'db> for ConcreteEnumId<'db> {
123 fn attributes_elements(&self, db: &'db dyn Database) -> Maybe<&'db [Attribute<'db>]> {
124 self.enum_id(db).attributes_elements(db)
125 }
126}
127impl<'db> SemanticQueryAttrs<'db> for ExternTypeId<'db> {
128 fn attributes_elements(&self, db: &'db dyn Database) -> Maybe<&'db [Attribute<'db>]> {
129 db.extern_type_attributes(*self)
130 }
131}
132impl<'db> SemanticQueryAttrs<'db> for ConcreteExternTypeId<'db> {
133 fn attributes_elements(&self, db: &'db dyn Database) -> Maybe<&'db [Attribute<'db>]> {
134 self.extern_type_id(db).attributes_elements(db)
135 }
136}
137impl<'db> SemanticQueryAttrs<'db> for SubmoduleId<'db> {
138 fn attributes_elements(&self, db: &'db dyn Database) -> Maybe<&'db [Attribute<'db>]> {
139 ModuleId::Submodule(*self).attributes_elements(db)
140 }
141}
142impl<'db> SemanticQueryAttrs<'db> for FreeFunctionId<'db> {
143 fn attributes_elements(&self, db: &'db dyn Database) -> Maybe<&'db [Attribute<'db>]> {
144 FunctionWithBodyId::Free(*self).attributes_elements(db)
145 }
146}
147
148impl<'db> SemanticQueryAttrs<'db> for TraitTypeId<'db> {
149 fn attributes_elements(&self, db: &'db dyn Database) -> Maybe<&'db [Attribute<'db>]> {
150 db.trait_type_attributes(*self)
151 }
152}
153impl<'db> SemanticQueryAttrs<'db> for TraitFunctionId<'db> {
154 fn attributes_elements(&self, db: &'db dyn Database) -> Maybe<&'db [Attribute<'db>]> {
155 db.trait_function_attributes(*self)
156 }
157}
158
159impl<'db> SemanticQueryAttrs<'db> for ImplTypeDefId<'db> {
160 fn attributes_elements(&self, db: &'db dyn Database) -> Maybe<&'db [Attribute<'db>]> {
161 db.impl_type_def_attributes(*self)
162 }
163}
164impl<'db> SemanticQueryAttrs<'db> for ImplFunctionId<'db> {
165 fn attributes_elements(&self, db: &'db dyn Database) -> Maybe<&'db [Attribute<'db>]> {
166 db.impl_function_attributes(*self)
167 }
168}