1use bitflags::bitflags;
7
8use crate::{
9 MacroId, ModuleDefId,
10 item_scope::{ImportId, ImportOrExternCrate, ImportOrGlob, ItemInNs},
11 visibility::Visibility,
12};
13
14#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
15pub enum Namespace {
16 Types,
17 Values,
18 Macros,
19}
20
21bitflags! {
22 #[derive(Debug, PartialEq, Eq)]
24 pub(crate) struct NsAvailability : u32 {
25 const TYPES = 1 << 0;
26 const VALUES = 1 << 1;
27 const MACROS = 1 << 2;
28 }
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
32pub struct Item<Def, Import = ImportId> {
33 pub def: Def,
34 pub vis: Visibility,
35 pub import: Option<Import>,
36}
37
38pub type TypesItem = Item<ModuleDefId, ImportOrExternCrate>;
39pub type ValuesItem = Item<ModuleDefId, ImportOrGlob>;
40pub type MacrosItem = Item<MacroId, ImportOrExternCrate>;
42
43#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
44pub struct PerNs {
45 pub types: Option<TypesItem>,
46 pub values: Option<ValuesItem>,
47 pub macros: Option<MacrosItem>,
48}
49
50impl PerNs {
51 pub(crate) fn availability(&self) -> NsAvailability {
52 let mut result = NsAvailability::empty();
53 result.set(NsAvailability::TYPES, self.types.is_some());
54 result.set(NsAvailability::VALUES, self.values.is_some());
55 result.set(NsAvailability::MACROS, self.macros.is_some());
56 result
57 }
58
59 pub fn none() -> PerNs {
60 PerNs { types: None, values: None, macros: None }
61 }
62
63 pub fn values(def: ModuleDefId, vis: Visibility, import: Option<ImportOrGlob>) -> PerNs {
64 PerNs { types: None, values: Some(Item { def, vis, import }), macros: None }
65 }
66
67 pub fn types(def: ModuleDefId, vis: Visibility, import: Option<ImportOrExternCrate>) -> PerNs {
68 PerNs { types: Some(Item { def, vis, import }), values: None, macros: None }
69 }
70
71 pub fn both(
72 types: ModuleDefId,
73 values: ModuleDefId,
74 vis: Visibility,
75 import: Option<ImportOrExternCrate>,
76 ) -> PerNs {
77 PerNs {
78 types: Some(Item { def: types, vis, import }),
79 values: Some(Item {
80 def: values,
81 vis,
82 import: import.and_then(ImportOrExternCrate::import_or_glob),
83 }),
84 macros: None,
85 }
86 }
87
88 pub fn macros(def: MacroId, vis: Visibility, import: Option<ImportOrExternCrate>) -> PerNs {
89 PerNs { types: None, values: None, macros: Some(Item { def, vis, import }) }
90 }
91
92 pub fn is_none(&self) -> bool {
93 self.types.is_none() && self.values.is_none() && self.macros.is_none()
94 }
95
96 pub fn is_full(&self) -> bool {
97 self.types.is_some() && self.values.is_some() && self.macros.is_some()
98 }
99
100 pub fn take_types(self) -> Option<ModuleDefId> {
101 self.types.map(|it| it.def)
102 }
103
104 pub fn take_types_full(self) -> Option<TypesItem> {
105 self.types
106 }
107
108 pub fn take_values(self) -> Option<ModuleDefId> {
109 self.values.map(|it| it.def)
110 }
111
112 pub fn take_values_import(self) -> Option<(ModuleDefId, Option<ImportOrGlob>)> {
113 self.values.map(|it| (it.def, it.import))
114 }
115
116 pub fn take_macros(self) -> Option<MacroId> {
117 self.macros.map(|it| it.def)
118 }
119
120 pub fn take_macros_import(self) -> Option<(MacroId, Option<ImportOrExternCrate>)> {
121 self.macros.map(|it| (it.def, it.import))
122 }
123
124 pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs {
125 let _p = tracing::info_span!("PerNs::filter_visibility").entered();
126 PerNs {
127 types: self.types.filter(|def| f(def.vis)),
128 values: self.values.filter(|def| f(def.vis)),
129 macros: self.macros.filter(|def| f(def.vis)),
130 }
131 }
132
133 pub fn with_visibility(self, vis: Visibility) -> PerNs {
134 PerNs {
135 types: self.types.map(|def| Item { vis, ..def }),
136 values: self.values.map(|def| Item { vis, ..def }),
137 macros: self.macros.map(|def| Item { vis, ..def }),
138 }
139 }
140
141 pub fn or(self, other: PerNs) -> PerNs {
142 PerNs {
143 types: self.types.or(other.types),
144 values: self.values.or(other.values),
145 macros: self.macros.or(other.macros),
146 }
147 }
148
149 pub fn or_else(self, f: impl FnOnce() -> PerNs) -> PerNs {
150 if self.is_full() { self } else { self.or(f()) }
151 }
152
153 pub fn iter_items(self) -> impl Iterator<Item = (ItemInNs, Option<ImportOrExternCrate>)> {
154 let _p = tracing::info_span!("PerNs::iter_items").entered();
155 self.types
156 .map(|it| (ItemInNs::Types(it.def), it.import))
157 .into_iter()
158 .chain(
159 self.values
160 .map(|it| (ItemInNs::Values(it.def), it.import.map(ImportOrExternCrate::from))),
161 )
162 .chain(self.macros.map(|it| (ItemInNs::Macros(it.def), it.import)))
163 }
164}