pilota_build/
resolve.rs

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}