gobject_linter/
type_alias_map.rs1use std::collections::{HashMap, HashSet};
2
3use gobject_ast::model::Project;
4
5pub struct TypeAliasMap {
8 typedef_to_tag: HashMap<String, String>,
9 tag_to_typedef: HashMap<String, String>,
10}
11
12impl TypeAliasMap {
13 pub fn build(project: &Project) -> Self {
14 let mut typedef_to_tag: HashMap<String, String> = HashMap::new();
15 let mut tag_to_typedef: HashMap<String, String> = HashMap::new();
16
17 for (_path, file) in project.files.iter().map(|(p, f)| (p.as_path(), f)) {
18 for (name, target) in file.iter_typedef_pairs() {
19 typedef_to_tag.insert(name.to_owned(), target.base_type.clone());
20 if target.is_struct || target.is_union {
21 tag_to_typedef.insert(target.base_type.clone(), name.to_owned());
22 }
23 }
24 for gt in file.iter_all_gobject_types() {
27 let tag = format!("_{}", gt.type_name);
28 typedef_to_tag
29 .entry(gt.type_name.clone())
30 .or_insert_with(|| tag.clone());
31 tag_to_typedef
32 .entry(tag)
33 .or_insert_with(|| gt.type_name.clone());
34 }
35 }
36
37 Self {
38 typedef_to_tag,
39 tag_to_typedef,
40 }
41 }
42
43 pub fn canonical<'a>(&'a self, name: &'a str) -> &'a str {
46 self.typedef_to_tag
47 .get(name)
48 .map_or(name, std::string::String::as_str)
49 }
50
51 pub fn typedef_for_tag<'a>(&'a self, tag: &'a str) -> Option<&'a str> {
53 self.tag_to_typedef
54 .get(tag)
55 .map(std::string::String::as_str)
56 }
57
58 pub fn tag_for_typedef<'a>(&'a self, name: &'a str) -> Option<&'a str> {
60 self.typedef_to_tag
61 .get(name)
62 .map(std::string::String::as_str)
63 }
64
65 pub fn is_referenced(&self, name: &str, refs: &HashSet<String>) -> bool {
67 refs.contains(name)
68 || self
69 .typedef_to_tag
70 .get(name)
71 .is_some_and(|t| refs.contains(t))
72 || self
73 .tag_to_typedef
74 .get(name)
75 .is_some_and(|a| refs.contains(a))
76 }
77
78 pub fn field_is_referenced(
81 &self,
82 struct_name: &str,
83 field_name: &str,
84 qualified: &HashMap<String, HashSet<String>>,
85 ) -> bool {
86 let has = |s: &str| {
87 qualified
88 .get(s)
89 .is_some_and(|fields| fields.contains(field_name))
90 };
91 has(struct_name)
92 || self.typedef_to_tag.get(struct_name).is_some_and(|t| has(t))
93 || self.tag_to_typedef.get(struct_name).is_some_and(|a| has(a))
94 }
95
96 pub fn insert_qualified(
99 &self,
100 type_name: &str,
101 field_name: &str,
102 qualified: &mut HashMap<String, HashSet<String>>,
103 ) {
104 qualified
105 .entry(type_name.to_owned())
106 .or_default()
107 .insert(field_name.to_owned());
108 if let Some(alias) = self.tag_to_typedef.get(type_name) {
109 qualified
110 .entry(alias.clone())
111 .or_default()
112 .insert(field_name.to_owned());
113 }
114 if let Some(tag) = self.typedef_to_tag.get(type_name) {
115 qualified
116 .entry(tag.clone())
117 .or_default()
118 .insert(field_name.to_owned());
119 }
120 }
121}