1use std::{ptr::NonNull, sync::Arc};
2
3use ahash::AHashMap;
4use itertools::Itertools;
5use rustc_hash::{FxHashMap, FxHashSet};
6
7use crate::{
8 errors,
9 index::Idx,
10 ir::{self, visit::Visitor},
11 middle::{
12 rir::{
13 Arg, Const, DefKind, Enum, EnumVariant, Extension as RirExtension, Field, FieldKind,
14 File, Item, ItemPath, Literal, Message, Method, MethodSource, NewType, Node, NodeKind,
15 Path, PbFieldType as RirPbFieldType, PbOptionsExtendee as RirPbExtendee, Service,
16 },
17 ty::{self, Ty},
18 },
19 rir::Mod,
20 symbol::{DefId, EnumRepr, FileId, Ident, Symbol},
21 tags::{RustType, RustWrapperArc, TagId, Tags, protobuf::OptionalRepeated},
22 ty::{Folder, TyKind},
23};
24
25struct ModuleData {
26 resolutions: SymbolTable,
27 _kind: DefKind,
28}
29
30#[derive(Clone, Copy)]
31enum ModuleId {
32 File(FileId),
33 Node(DefId),
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37enum Namespace {
38 Value,
39 Ty,
40 Mod,
41}
42
43pub struct CollectDef<'a> {
44 resolver: &'a mut Resolver,
45 parent: Option<ModuleId>,
46}
47
48impl<'a> CollectDef<'a> {
49 pub fn new(resolver: &'a mut Resolver) -> Self {
50 CollectDef {
51 resolver,
52 parent: None,
53 }
54 }
55}
56
57impl CollectDef<'_> {
58 fn def_item(&mut self, item: &ir::Item, ns: Namespace) -> DefId {
59 let parent = self.parent.as_ref().unwrap();
60 let did = self.resolver.did_counter.inc_one();
61 let table = match parent {
62 ModuleId::File(file_id) => self.resolver.file_sym_map.entry(*file_id).or_default(),
63 ModuleId::Node(def_id) => {
64 &mut self
65 .resolver
66 .def_modules
67 .get_mut(def_id)
68 .unwrap()
69 .resolutions
70 }
71 };
72
73 let name = item.name();
74
75 tracing::debug!("def {} with DefId({:?})", name, did);
76
77 if match ns {
78 Namespace::Value => table.value.insert(name.clone(), did),
79 Namespace::Ty => table.ty.insert(name.clone(), did),
80 Namespace::Mod => table.mods.insert(name.clone(), did),
81 }
82 .is_some()
83 {
84 self.resolver
85 .errors
86 .emit_error(format!("duplicate definition of `{name}`"));
87 };
88
89 self.resolver.def_modules.insert(
90 did,
91 ModuleData {
92 resolutions: Default::default(),
93 _kind: match &item.kind {
94 ir::ItemKind::Message(_)
95 | ir::ItemKind::Enum(_)
96 | ir::ItemKind::Service(_)
97 | ir::ItemKind::NewType(_) => DefKind::Type,
98 ir::ItemKind::Const(_) => DefKind::Value,
99 ir::ItemKind::Mod(_) => DefKind::Mod,
100 ir::ItemKind::Use(_) => unreachable!(),
101 },
102 },
103 );
104
105 did
106 }
107
108 fn def_sym(&mut self, ns: Namespace, sym: Symbol) {
109 let parent = match self.parent.unwrap() {
110 ModuleId::File(_) => panic!(),
111 ModuleId::Node(def_id) => def_id,
112 };
113
114 tracing::debug!("def {} for {:?} in {:?}", sym, parent, ns);
115
116 let table = match ns {
117 Namespace::Value => {
118 &mut self
119 .resolver
120 .def_modules
121 .get_mut(&parent)
122 .unwrap()
123 .resolutions
124 .value
125 }
126 Namespace::Ty => {
127 &mut self
128 .resolver
129 .def_modules
130 .get_mut(&parent)
131 .unwrap()
132 .resolutions
133 .ty
134 }
135 Namespace::Mod => {
136 &mut self
137 .resolver
138 .def_modules
139 .get_mut(&parent)
140 .unwrap()
141 .resolutions
142 .mods
143 }
144 };
145 let def_id = self.resolver.did_counter.inc_one();
146 table.insert(sym, def_id);
147 }
148}
149
150impl ir::visit::Visitor for CollectDef<'_> {
151 fn visit_file(&mut self, file: Arc<ir::File>) {
152 self.parent = Some(ModuleId::File(file.id));
153 ir::visit::walk_file(self, file);
154 self.parent = None;
155 }
156
157 fn visit_item(&mut self, item: Arc<ir::Item>) {
158 if let Some(did) = match &item.kind {
159 ir::ItemKind::Message(_)
160 | ir::ItemKind::Enum(_)
161 | ir::ItemKind::Service(_)
162 | ir::ItemKind::NewType(_) => Some(self.def_item(&item, Namespace::Ty)),
163 ir::ItemKind::Const(_) => Some(self.def_item(&item, Namespace::Value)),
164 ir::ItemKind::Mod(_) => Some(self.def_item(&item, Namespace::Mod)),
165 ir::ItemKind::Use(_) => None,
166 } {
167 let prev_parent = self.parent.replace(ModuleId::Node(did));
168 if let ir::ItemKind::Enum(e) = &item.kind {
169 e.variants.iter().for_each(|e| {
170 self.def_sym(Namespace::Value, (*e.name).clone());
171 })
172 }
173 ir::visit::walk_item(self, item);
174 self.parent = prev_parent;
175 }
176 }
177}
178
179#[derive(Default, Debug)]
180pub struct SymbolTable {
181 pub(crate) value: AHashMap<Symbol, DefId>,
182 pub(crate) ty: AHashMap<Symbol, DefId>,
183 pub(crate) mods: AHashMap<Symbol, DefId>,
184}
185
186pub struct Resolver {
187 pub(crate) did_counter: DefId,
188 pub(crate) file_sym_map: FxHashMap<FileId, SymbolTable>,
189 def_modules: FxHashMap<DefId, ModuleData>,
190 blocks: Vec<NonNull<SymbolTable>>,
191 parent_node: Option<DefId>,
192 nodes: FxHashMap<DefId, Node>,
193 tags_id_counter: TagId,
194 tags: FxHashMap<TagId, Arc<Tags>>,
195 cur_file: Option<FileId>,
196 ir_files: FxHashMap<FileId, Arc<ir::File>>,
197 errors: errors::Handler,
198 args: FxHashSet<DefId>,
199}
200
201impl Default for Resolver {
202 fn default() -> Self {
203 Resolver {
204 tags_id_counter: TagId::from_usize(0),
205 tags: Default::default(),
206 blocks: Default::default(),
207 def_modules: Default::default(),
208 did_counter: DefId::from_usize(0),
209 file_sym_map: Default::default(),
210 nodes: Default::default(),
211 ir_files: Default::default(),
212 errors: Default::default(),
213 cur_file: None,
214 parent_node: None,
215 args: Default::default(),
216 }
217 }
218}
219
220pub struct ResolveResult {
221 pub files: FxHashMap<FileId, Arc<File>>,
222 pub nodes: FxHashMap<DefId, Node>,
223 pub tags: FxHashMap<TagId, Arc<Tags>>,
224 pub args: FxHashSet<DefId>,
225}
226
227pub struct ResolvedSymbols {
228 ty: Vec<DefId>,
229 value: Vec<DefId>,
230 r#mod: Vec<DefId>,
231}
232
233impl Resolver {
234 fn get_def_id(&self, ns: Namespace, sym: &Symbol) -> DefId {
235 if let Some(parent) = self.parent_node {
236 *match ns {
237 Namespace::Value => self.def_modules[&parent].resolutions.value.get(sym),
238 Namespace::Ty => self.def_modules[&parent].resolutions.ty.get(sym),
239 Namespace::Mod => self.def_modules[&parent].resolutions.mods.get(sym),
240 }
241 .unwrap()
242 } else {
243 let cur_file = &self.file_sym_map[&self.cur_file.unwrap()];
244 *match ns {
245 Namespace::Value => cur_file.value.get(sym),
246 Namespace::Ty => cur_file.ty.get(sym),
247 Namespace::Mod => cur_file.mods.get(sym),
248 }
249 .unwrap()
250 }
251 }
252
253 pub fn resolve_files(mut self, files: &[Arc<ir::File>]) -> ResolveResult {
254 files.iter().for_each(|f| {
255 let mut collect = CollectDef::new(&mut self);
256 collect.visit_file(f.clone());
257 self.ir_files.insert(f.id, f.clone());
258 });
259
260 self.errors.abort_if_errors();
261
262 let files = files
263 .iter()
264 .map(|f| (f.id, Arc::from(self.lower_file(f))))
265 .collect::<FxHashMap<_, _>>();
266
267 self.errors.abort_if_errors();
268
269 ResolveResult {
270 tags: self.tags,
271 files,
272 nodes: self.nodes,
273 args: self.args,
274 }
275 }
276
277 fn modify_ty_by_tags(&mut self, mut ty: Ty, tags: &Tags) -> Ty {
278 match ty.kind {
279 ty::FastStr
280 if tags
281 .get::<RustType>()
282 .map(|repr| repr == "string")
283 .unwrap_or(false) =>
284 {
285 ty.kind = ty::String;
286 }
287 ty::Bytes
288 if tags
289 .get::<RustType>()
290 .map(|repr| repr == "vec")
291 .unwrap_or(false) =>
292 {
293 ty.kind = ty::BytesVec;
294 }
295 _ => {}
296 }
297
298 if let Some(repr) = tags.get::<RustType>() {
299 if repr == "btree" {
300 struct BTreeFolder;
301 impl Folder for BTreeFolder {
302 fn fold_ty(&mut self, ty: &Ty) -> Ty {
303 let kind = match &ty.kind {
304 TyKind::Vec(inner) => {
305 TyKind::Vec(Arc::new(self.fold_ty(inner.as_ref())))
306 }
307 TyKind::Set(inner) => {
308 TyKind::BTreeSet(Arc::new(self.fold_ty(inner.as_ref())))
309 }
310 TyKind::Map(k, v) => TyKind::BTreeMap(
311 Arc::new(self.fold_ty(k.as_ref())),
312 Arc::new(self.fold_ty(v.as_ref())),
313 ),
314 kind => kind.clone(),
315 };
316 Ty {
317 kind,
318 tags_id: ty.tags_id,
319 }
320 }
321 }
322 ty = BTreeFolder.fold_ty(&ty);
323 } else if repr == "ordered_f64" {
324 ty.kind = ty::OrderedF64;
325 }
326 };
327
328 if let Some(RustWrapperArc(true)) = tags.get::<RustWrapperArc>() {
329 struct ArcFolder;
330 impl Folder for ArcFolder {
331 fn fold_ty(&mut self, ty: &Ty) -> Ty {
332 let kind = match &ty.kind {
333 TyKind::Vec(inner) => TyKind::Vec(Arc::new(self.fold_ty(inner.as_ref()))),
334 TyKind::Set(inner) => TyKind::Set(Arc::new(self.fold_ty(inner.as_ref()))),
335 TyKind::BTreeSet(inner) => {
336 TyKind::BTreeSet(Arc::new(self.fold_ty(inner.as_ref())))
337 }
338 TyKind::Map(k, v) => {
339 TyKind::Map(k.clone(), Arc::new(self.fold_ty(v.as_ref())))
340 }
341 TyKind::BTreeMap(k, v) => {
342 TyKind::BTreeMap(k.clone(), Arc::new(self.fold_ty(v.as_ref())))
343 }
344 TyKind::Path(_) | TyKind::String | TyKind::BytesVec => {
345 TyKind::Arc(Arc::new(ty.clone()))
346 }
347 _ => panic!("ty: {ty:?} is unnecessary to be wrapped by Arc"),
348 };
349 Ty {
350 kind,
351 tags_id: ty.tags_id,
352 }
353 }
354 }
355 ArcFolder.fold_ty(&ty)
356 } else {
357 ty
358 }
359 }
360
361 #[tracing::instrument(level = "debug", skip_all, fields(name = &**f.name))]
362 fn lower_field(&mut self, f: &ir::Field) -> Arc<Field> {
363 tracing::info!("lower filed {}, ty: {:?}", f.name, f.ty.kind);
364 let did = self.did_counter.inc_one();
365 let tags_id = self.tags_id_counter.inc_one();
366 self.tags.insert(tags_id, f.tags.clone());
367 let ty = self.lower_type(&f.ty, false);
368 let ty = self.modify_ty_by_tags(ty, &f.tags);
369
370 let mut kind = match f.kind {
371 ir::FieldKind::Required => FieldKind::Required,
372 ir::FieldKind::Optional => FieldKind::Optional,
373 };
374 if let Some(OptionalRepeated(true)) = f.tags.get::<OptionalRepeated>() {
375 kind = FieldKind::Optional;
376 }
377
378 let f = Arc::from(Field {
379 did,
380 id: f.id,
381 kind,
382 name: f.name.clone(),
383 ty,
384 tags_id,
385 default: f.default.as_ref().map(|d| self.lower_lit(d)),
386 });
387
388 self.nodes
389 .insert(did, self.mk_node(NodeKind::Field(f.clone()), tags_id));
390
391 f
392 }
393
394 fn mk_node(&self, kind: NodeKind, tags: TagId) -> Node {
395 Node {
396 related_nodes: Default::default(),
397 tags,
398 parent: self.parent_node,
399 file_id: self.cur_file.unwrap(),
400 kind,
401 }
402 }
403
404 fn lower_type(&mut self, ty: &ir::Ty, is_args: bool) -> Ty {
405 let kind = match &ty.kind {
406 ir::TyKind::String => ty::FastStr,
407 ir::TyKind::Void => ty::Void,
408 ir::TyKind::U8 => ty::U8,
409 ir::TyKind::Bool => ty::Bool,
410 ir::TyKind::Bytes => ty::Bytes,
411 ir::TyKind::I8 => ty::I8,
412 ir::TyKind::I16 => ty::I16,
413 ir::TyKind::I32 => ty::I32,
414 ir::TyKind::I64 => ty::I64,
415 ir::TyKind::F64 => ty::F64,
416 ir::TyKind::Uuid => ty::Uuid,
417 ir::TyKind::Vec(ty) => ty::Vec(Arc::from(self.lower_type(ty, false))),
418 ir::TyKind::Set(ty) => ty::Set(Arc::from(self.lower_type_for_hash_key(ty, false))),
419 ir::TyKind::Map(k, v) => ty::Map(
420 Arc::from(self.lower_type_for_hash_key(k, false)),
421 Arc::from(self.lower_type(v, false)),
422 ),
423 ir::TyKind::Path(p) => ty::Path(self.lower_path(p, Namespace::Ty, is_args)),
424 ir::TyKind::UInt64 => ty::UInt64,
425 ir::TyKind::UInt32 => ty::UInt32,
426 ir::TyKind::F32 => ty::F32,
427 };
428 let tags_id = self.tags_id_counter.inc_one();
429
430 self.tags.insert(tags_id, ty.tags.clone());
431
432 Ty { kind, tags_id }
433 }
434
435 fn lower_type_for_hash_key(&mut self, ty: &ir::Ty, is_args: bool) -> Ty {
436 let kind = match &ty.kind {
437 ir::TyKind::String => ty::FastStr,
438 ir::TyKind::Void => ty::Void,
439 ir::TyKind::U8 => ty::U8,
440 ir::TyKind::Bool => ty::Bool,
441 ir::TyKind::Bytes => ty::Bytes,
442 ir::TyKind::I8 => ty::I8,
443 ir::TyKind::I16 => ty::I16,
444 ir::TyKind::I32 => ty::I32,
445 ir::TyKind::I64 => ty::I64,
446 ir::TyKind::F64 => ty::OrderedF64,
447 ir::TyKind::Uuid => ty::Uuid,
448 ir::TyKind::Vec(ty) => ty::Vec(Arc::from(self.lower_type_for_hash_key(ty, false))),
449 ir::TyKind::Set(ty) => ty::Set(Arc::from(self.lower_type_for_hash_key(ty, false))),
450 ir::TyKind::Map(k, v) => ty::Map(
451 Arc::from(self.lower_type_for_hash_key(k, false)),
452 Arc::from(self.lower_type(v, false)),
453 ),
454 ir::TyKind::Path(p) => ty::Path(self.lower_path(p, Namespace::Ty, is_args)),
455 ir::TyKind::UInt64 => ty::UInt64,
456 ir::TyKind::UInt32 => ty::UInt32,
457 ir::TyKind::F32 => ty::F32,
458 };
459 let tags_id = self.tags_id_counter.inc_one();
460
461 self.tags.insert(tags_id, ty.tags.clone());
462
463 Ty { kind, tags_id }
464 }
465
466 fn find_path_in_table(
467 &self,
468 path: &[Ident],
469 ns: Namespace,
470 table: &SymbolTable,
471 ) -> Option<DefId> {
472 assert!(!path.is_empty());
473 let mut status: ResolvedSymbols = ResolvedSymbols {
474 ty: table
475 .ty
476 .get(&path[0].sym)
477 .map_or_else(Default::default, |s| vec![*s]),
478 value: table
479 .value
480 .get(&path[0].sym)
481 .map_or_else(Default::default, |s| vec![*s]),
482 r#mod: table
483 .mods
484 .get(&path[0].sym)
485 .map_or_else(Default::default, |s| vec![*s]),
486 };
487
488 path[1..].iter().for_each(|i| {
489 status = ResolvedSymbols {
490 ty: [&status.ty, &status.value, &status.r#mod]
491 .into_iter()
492 .flatten()
493 .flat_map(|def_id| {
494 self.def_modules
495 .get(def_id)
496 .and_then(|module| module.resolutions.ty.get(&i.sym))
497 })
498 .copied()
499 .collect(),
500 value: [&status.ty, &status.value, &status.r#mod]
501 .into_iter()
502 .flatten()
503 .flat_map(|def_id| {
504 self.def_modules
505 .get(def_id)
506 .and_then(|module| module.resolutions.value.get(&i.sym))
507 })
508 .copied()
509 .collect(),
510 r#mod: [&status.ty, &status.value, &status.r#mod]
511 .into_iter()
512 .flatten()
513 .flat_map(|def_id| {
514 self.def_modules
515 .get(def_id)
516 .and_then(|module| module.resolutions.mods.get(&i.sym))
517 })
518 .copied()
519 .collect_vec(),
520 };
521 });
522
523 assert!(status.value.len() <= 1);
524 assert!(status.ty.len() <= 1);
525 assert!(status.r#mod.len() <= 1);
526
527 match ns {
528 Namespace::Value => status.value.first(),
529 Namespace::Ty => status.ty.first(),
530 Namespace::Mod => status.r#mod.first(),
531 }
532 .copied()
533 }
534
535 fn lower_path(&mut self, path: &ir::Path, ns: Namespace, is_args: bool) -> Path {
536 let segs = &path.segments;
537 let cur_file = self.ir_files.get(self.cur_file.as_ref().unwrap()).unwrap();
538 let path_kind = match ns {
539 Namespace::Value => DefKind::Value,
540 Namespace::Ty => DefKind::Type,
541 Namespace::Mod => unreachable!(),
542 };
543 {
544 let segs = match segs.strip_prefix(&*cur_file.package.segments) {
545 Some(segs) => segs,
546 _ => segs,
547 };
548
549 let def_id = self.blocks.iter().rev().find_map(|b| {
550 let b = unsafe { b.as_ref() };
551 self.find_path_in_table(segs, ns, b)
552 });
553
554 if let Some(def_id) = def_id {
555 if is_args {
556 self.args.insert(def_id);
557 }
558 return Path {
559 kind: path_kind,
560 did: def_id,
561 };
562 }
563 }
564 let def_id = cur_file
565 .uses
566 .iter()
567 .find_map(|f| match path.segments.strip_prefix(&*f.0.segments) {
568 Some(rest) => {
569 let file = &self.file_sym_map[&f.1];
570 self.find_path_in_table(rest, ns, file)
571 }
572 _ => None,
573 })
574 .unwrap_or_else(|| {
575 panic!(
576 "can not find path {} in file symbols {:?}, {:?}",
577 path,
578 self.file_sym_map.get(&self.cur_file.unwrap()),
579 cur_file.uses,
580 )
581 });
582
583 if is_args {
584 self.args.insert(def_id);
585 }
586 Path {
587 kind: path_kind,
588 did: def_id,
589 }
590 }
591
592 #[tracing::instrument(level = "debug", skip(self, s), fields(name = &**s.name))]
593 fn lower_message(&mut self, s: &ir::Message) -> Message {
594 Message {
595 name: s.name.clone(),
596 fields: s.fields.iter().map(|f| self.lower_field(f)).collect(),
597 is_wrapper: s.is_wrapper,
598 extensions: s
599 .extensions
600 .iter()
601 .filter_map(|e| self.lower_extension(e))
602 .collect(),
603 }
604 }
605
606 fn lower_enum(&mut self, e: &ir::Enum) -> Enum {
607 let mut next_discr = 0;
608 Enum {
609 name: e.name.clone(),
610 variants: e
611 .variants
612 .iter()
613 .map(|v| {
614 let tags_id = self.tags_id_counter.inc_one();
615 let did = self.get_def_id(Namespace::Value, &v.name);
616 if !v.tags.is_empty() {
617 self.tags.insert(tags_id, v.tags.clone());
618 }
619 let discr = v.discr.unwrap_or(next_discr);
620 let e = Arc::from(EnumVariant {
621 id: v.id,
622 did,
623 name: v.name.clone(),
624 discr: if e.repr == Some(EnumRepr::I32) {
625 Some(discr)
626 } else {
627 None
628 },
629 fields: v
630 .fields
631 .iter()
632 .map(|p| {
633 let ty = self.lower_type(p, false);
634 self.modify_ty_by_tags(ty, &p.tags)
635 })
636 .collect(),
637 });
638 next_discr = discr + 1;
639 self.nodes
640 .insert(did, self.mk_node(NodeKind::Variant(e.clone()), tags_id));
641 e
642 })
643 .collect(),
644 repr: e.repr,
645 }
646 }
647
648 fn lower_service(&mut self, s: &ir::Service) -> Service {
649 Service {
650 name: s.name.clone(),
651 methods: s
652 .methods
653 .iter()
654 .map(|m| {
655 let def_id = self.did_counter.inc_one();
656 let tags_id = self.tags_id_counter.inc_one();
657 self.tags.insert(tags_id, m.tags.clone());
658 let old_parent = self.parent_node.replace(def_id);
659 let method = Arc::from(Method {
660 def_id,
661 source: MethodSource::Own,
662 name: m.name.clone(),
663 args: m
664 .args
665 .iter()
666 .map(|a| {
667 let tags_id = self.tags_id_counter.inc_one();
668 self.tags.insert(tags_id, a.tags.clone());
669 let def_id = self.did_counter.inc_one();
670 let arg = Arc::new(Arg {
671 def_id,
672 ty: self.lower_type(&a.ty, true),
673 name: a.name.clone(),
674 id: a.id,
675 tags_id,
676 kind: match a.attribute {
677 ir::FieldKind::Required => FieldKind::Required,
678 ir::FieldKind::Optional => FieldKind::Optional,
679 },
680 });
681 self.nodes.insert(
682 def_id,
683 self.mk_node(NodeKind::Arg(arg.clone()), tags_id),
684 );
685 arg
686 })
687 .collect(),
688 ret: self.lower_type(&m.ret, true),
689 oneway: m.oneway,
690 exceptions: m
691 .exceptions
692 .as_ref()
693 .map(|p| self.lower_path(p, Namespace::Ty, true)),
694 });
695 self.parent_node = old_parent;
696 self.nodes.insert(
697 def_id,
698 self.mk_node(NodeKind::Method(method.clone()), tags_id),
699 );
700
701 method
702 })
703 .collect(),
704 extend: s
705 .extend
706 .iter()
707 .map(|p| self.lower_path(p, Namespace::Ty, false))
708 .collect(),
709 }
710 }
711
712 fn lower_type_alias(&mut self, t: &ir::NewType, tags: &Tags) -> NewType {
713 NewType {
714 name: t.name.clone(),
715 ty: {
716 let ty = self.lower_type(&t.ty, false);
717 self.modify_ty_by_tags(ty, tags)
718 },
719 }
720 }
721
722 fn lower_lit(&mut self, l: &ir::Literal) -> Literal {
723 match l {
724 ir::Literal::Bool(b) => Literal::Bool(*b),
725 ir::Literal::Path(p) => Literal::Path(self.lower_path(p, Namespace::Value, false)),
726 ir::Literal::String(s) => Literal::String(s.clone()),
727 ir::Literal::Int(i) => Literal::Int(*i),
728 ir::Literal::Float(f) => Literal::Float(f.clone()),
729 ir::Literal::List(l) => Literal::List(l.iter().map(|l| self.lower_lit(l)).collect()),
730 ir::Literal::Map(l) => Literal::Map(
731 l.iter()
732 .map(|(k, v)| (self.lower_lit(k), self.lower_lit(v)))
733 .collect(),
734 ),
735 }
736 }
737
738 fn lower_const(&mut self, c: &ir::Const, tags: &Tags) -> Const {
739 Const {
740 name: c.name.clone(),
741 ty: {
742 let ty = self.lower_type(&c.ty, false);
743 self.modify_ty_by_tags(ty, tags)
744 },
745 lit: self.lower_lit(&c.lit),
746 }
747 }
748
749 fn lower_mod(&mut self, m: &ir::Mod, def_id: DefId) -> Mod {
750 self.blocks.push(NonNull::from(
751 &self.def_modules.get(&def_id).unwrap().resolutions,
752 ));
753
754 let items = m
755 .items
756 .iter()
757 .filter_map(|i| self.lower_item(i))
758 .collect::<Vec<_>>();
759
760 self.blocks.pop();
761
762 Mod {
763 name: m.name.clone(),
764 items,
765 extensions: m
766 .extensions
767 .iter()
768 .filter_map(|e| self.lower_extension(e))
769 .collect(),
770 }
771 }
772
773 fn lower_item(&mut self, item: &ir::Item) -> Option<DefId> {
774 if let ir::ItemKind::Use(_) = &item.kind {
775 return None;
776 }
777
778 let name = item.name();
779 let tags = &item.tags;
780
781 let def_id = self.get_def_id(
782 match &item.kind {
783 ir::ItemKind::Const(_) => Namespace::Value,
784 ir::ItemKind::Mod(_) => Namespace::Mod,
785 _ => Namespace::Ty,
786 },
787 &name,
788 );
789
790 let old_parent = self.parent_node.replace(def_id);
791 let related_items = &item.related_items;
792
793 let item = Arc::new(match &item.kind {
794 ir::ItemKind::Message(s) => Item::Message(self.lower_message(s)),
795 ir::ItemKind::Enum(e) => Item::Enum(self.lower_enum(e)),
796 ir::ItemKind::Service(s) => Item::Service(self.lower_service(s)),
797 ir::ItemKind::NewType(t) => Item::NewType(self.lower_type_alias(t, tags)),
798 ir::ItemKind::Const(c) => Item::Const(self.lower_const(c, tags)),
799 ir::ItemKind::Mod(m) => Item::Mod(self.lower_mod(m, def_id)),
800 ir::ItemKind::Use(_) => unreachable!(),
801 });
802
803 self.parent_node = old_parent;
804
805 let tags_id = self.tags_id_counter.inc_one();
806 self.tags.insert(tags_id, tags.clone());
807
808 let mut node = self.mk_node(NodeKind::Item(item), tags_id);
809 node.related_nodes = related_items
810 .iter()
811 .map(|i| {
812 self.lower_path(
813 &ir::Path {
814 segments: Arc::from([i.clone()]),
815 },
816 Namespace::Ty,
817 false,
818 )
819 .did
820 })
821 .collect();
822
823 self.nodes.insert(def_id, node);
824
825 Some(def_id)
826 }
827
828 fn lower_file(&mut self, file: &ir::File) -> File {
829 let old_file = self.cur_file.replace(file.id);
830 let should_pop = self
831 .file_sym_map
832 .get(&file.id)
833 .map(|block| self.blocks.push(NonNull::from(block)))
834 .is_some();
835
836 let f = File {
837 items: file
838 .items
839 .iter()
840 .filter_map(|item| self.lower_item(item))
841 .collect(),
842
843 file_id: file.id,
844 package: ItemPath::from(
845 file.package
846 .segments
847 .iter()
848 .map(|i| i.sym.clone())
849 .collect::<Vec<_>>(),
850 ),
851 uses: file.uses.iter().map(|(_, f)| *f).collect(),
852 descriptor: file.descriptor.clone(),
853 extensions: file
854 .extensions
855 .iter()
856 .filter_map(|e| self.lower_extension(e))
857 .collect(),
858 };
859
860 if should_pop {
861 self.blocks.pop();
862 }
863
864 self.cur_file = old_file;
865 f
866 }
867
868 fn lower_extension(&mut self, e: &ir::Extension) -> Option<RirExtension> {
869 let extendee = match e.extendee {
870 ir::PbOptionsExtendee::File => RirPbExtendee::File,
871 ir::PbOptionsExtendee::Message => RirPbExtendee::Message,
872 ir::PbOptionsExtendee::Field => RirPbExtendee::Field,
873 ir::PbOptionsExtendee::Enum => RirPbExtendee::Enum,
874 ir::PbOptionsExtendee::EnumValue => RirPbExtendee::EnumValue,
875 ir::PbOptionsExtendee::Service => RirPbExtendee::Service,
876 ir::PbOptionsExtendee::Method => RirPbExtendee::Method,
877 ir::PbOptionsExtendee::Oneof => RirPbExtendee::Oneof,
878 };
879 let field_ty = match e.field_ty {
880 ir::PbFieldType::Bool => RirPbFieldType::Bool,
881 ir::PbFieldType::Int32 => RirPbFieldType::Int32,
882 ir::PbFieldType::Int64 => RirPbFieldType::Int64,
883 ir::PbFieldType::UInt32 => RirPbFieldType::UInt32,
884 ir::PbFieldType::UInt64 => RirPbFieldType::UInt64,
885 ir::PbFieldType::Float => RirPbFieldType::Float,
886 ir::PbFieldType::Double => RirPbFieldType::Double,
887 ir::PbFieldType::String => RirPbFieldType::String,
888 ir::PbFieldType::Bytes => RirPbFieldType::Bytes,
889 ir::PbFieldType::Message => RirPbFieldType::Message,
890 ir::PbFieldType::Enum => RirPbFieldType::Enum,
891 };
892 Some(RirExtension {
893 name: e.name.clone(),
894 number: e.number,
895 field_ty,
896 extendee,
897 value_ty: self.lower_type(&e.value_ty, false),
898 })
899 }
900}