1 //! Intermediate representation for modules (AKA C++ namespaces).
2 
3 use super::context::BindgenContext;
4 use super::dot::DotAttributes;
5 use super::item::ItemSet;
6 use crate::clang;
7 use crate::parse::{ClangSubItemParser, ParseError, ParseResult};
8 use crate::parse_one;
9 
10 use std::io;
11 
12 /// Whether this module is inline or not.
13 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
14 pub(crate) enum ModuleKind {
15     /// This module is not inline.
16     Normal,
17     /// This module is inline, as in `inline namespace foo {}`.
18     Inline,
19 }
20 
21 /// A module, as in, a C++ namespace.
22 #[derive(Clone, Debug)]
23 pub(crate) struct Module {
24     /// The name of the module, or none if it's anonymous.
25     name: Option<String>,
26     /// The kind of module this is.
27     kind: ModuleKind,
28     /// The children of this module, just here for convenience.
29     children: ItemSet,
30 }
31 
32 impl Module {
33     /// Construct a new `Module`.
new(name: Option<String>, kind: ModuleKind) -> Self34     pub(crate) fn new(name: Option<String>, kind: ModuleKind) -> Self {
35         Module {
36             name,
37             kind,
38             children: ItemSet::new(),
39         }
40     }
41 
42     /// Get this module's name.
name(&self) -> Option<&str>43     pub(crate) fn name(&self) -> Option<&str> {
44         self.name.as_deref()
45     }
46 
47     /// Get a mutable reference to this module's children.
children_mut(&mut self) -> &mut ItemSet48     pub(crate) fn children_mut(&mut self) -> &mut ItemSet {
49         &mut self.children
50     }
51 
52     /// Get this module's children.
children(&self) -> &ItemSet53     pub(crate) fn children(&self) -> &ItemSet {
54         &self.children
55     }
56 
57     /// Whether this namespace is inline.
is_inline(&self) -> bool58     pub(crate) fn is_inline(&self) -> bool {
59         self.kind == ModuleKind::Inline
60     }
61 }
62 
63 impl DotAttributes for Module {
dot_attributes<W>( &self, _ctx: &BindgenContext, out: &mut W, ) -> io::Result<()> where W: io::Write,64     fn dot_attributes<W>(
65         &self,
66         _ctx: &BindgenContext,
67         out: &mut W,
68     ) -> io::Result<()>
69     where
70         W: io::Write,
71     {
72         writeln!(out, "<tr><td>ModuleKind</td><td>{:?}</td></tr>", self.kind)
73     }
74 }
75 
76 impl ClangSubItemParser for Module {
parse( cursor: clang::Cursor, ctx: &mut BindgenContext, ) -> Result<ParseResult<Self>, ParseError>77     fn parse(
78         cursor: clang::Cursor,
79         ctx: &mut BindgenContext,
80     ) -> Result<ParseResult<Self>, ParseError> {
81         use clang_sys::*;
82         match cursor.kind() {
83             CXCursor_Namespace => {
84                 let module_id = ctx.module(cursor);
85                 ctx.with_module(module_id, |ctx| {
86                     cursor.visit_sorted(ctx, |ctx, child| {
87                         parse_one(ctx, child, Some(module_id.into()))
88                     })
89                 });
90 
91                 Ok(ParseResult::AlreadyResolved(module_id.into()))
92             }
93             _ => Err(ParseError::Continue),
94         }
95     }
96 }
97