Implement reopened namespaces

For a series of 3 reopened namespaces under the name of outer and inner we generate the following code:

```
pub mod outer_0 {
    pub mod inner_0 {}
}

pub mod outer_1 {
    pub use super::outer_0::*;
    pub mod inner_1 {
        pub use super::inner_0::*;
    }
}

pub mod outer {
    pub use super::outer_1::*;
    pub mod inner {
        pub use super::inner_1::*;
    }
}
```

For this we add two helper maps into our ir:

map <ItemId, usize> => canonical namespace id to number of reopened namespaces

map <ItemId, usize> => reopened namespace id to its ordinal number

PiperOrigin-RevId: 452288159
diff --git a/rs_bindings_from_cc/importer.cc b/rs_bindings_from_cc/importer.cc
index 521f83d..6584556 100644
--- a/rs_bindings_from_cc/importer.cc
+++ b/rs_bindings_from_cc/importer.cc
@@ -38,6 +38,7 @@
 #include "clang/AST/RawCommentList.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/FileManager.h"
+#include "clang/Basic/LLVM.h"
 #include "clang/Basic/OperatorKinds.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
@@ -304,7 +305,12 @@
   while (!decls_to_visit.empty()) {
     clang::Decl* child = decls_to_visit.back();
     decls_to_visit.pop_back();
-    auto decl = child->getCanonicalDecl();
+    clang::Decl* decl;
+    if (auto namespace_decl = llvm::dyn_cast<clang::NamespaceDecl>(child)) {
+      decl = namespace_decl;
+    } else {
+      decl = child->getCanonicalDecl();
+    }
     if (!IsFromCurrentTarget(decl)) continue;
 
     if (const auto* linkage_spec_decl =
@@ -428,9 +434,13 @@
             llvm::dyn_cast<clang::LinkageSpecDecl>(decl)) {
       ImportDeclsFromDeclContext(linkage_spec_decl);
     } else {
-      // TODO(rosica): We don't always want the canonical decl here (especially
-      // not in namespaces).
-      GetDeclItem(decl->getCanonicalDecl());
+      clang::Decl* decl_to_import;
+      if (auto namespace_decl = llvm::dyn_cast<clang::NamespaceDecl>(decl)) {
+        decl_to_import = namespace_decl;
+      } else {
+        decl_to_import = decl->getCanonicalDecl();
+      }
+      GetDeclItem(decl_to_import);
     }
   }
 }
diff --git a/rs_bindings_from_cc/ir.rs b/rs_bindings_from_cc/ir.rs
index 335a0f3..4b003f6 100644
--- a/rs_bindings_from_cc/ir.rs
+++ b/rs_bindings_from_cc/ir.rs
@@ -67,7 +67,32 @@
             }
         }
     }
-    Ok(IR { flat_ir, item_id_to_item_idx, lifetimes })
+    let mut namespace_id_to_number_of_reopened_namespaces = HashMap::new();
+    let mut reopened_namespace_id_to_idx = HashMap::new();
+
+    flat_ir
+        .items
+        .iter()
+        .filter_map(|item| match item {
+            Item::Namespace(ns) if ns.owning_target == flat_ir.current_target => {
+                Some((ns.canonical_namespace_id, ns.id))
+            }
+            _ => None,
+        })
+        .for_each(|(canonical_id, id)| {
+            let current_count =
+                *namespace_id_to_number_of_reopened_namespaces.entry(canonical_id).or_insert(0);
+            reopened_namespace_id_to_idx.insert(id, current_count);
+            namespace_id_to_number_of_reopened_namespaces.insert(canonical_id, current_count + 1);
+        });
+
+    Ok(IR {
+        flat_ir,
+        item_id_to_item_idx,
+        lifetimes,
+        namespace_id_to_number_of_reopened_namespaces,
+        reopened_namespace_id_to_idx,
+    })
 }
 
 #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)]
@@ -595,6 +620,8 @@
     // A map from a `decl_id` to an index of an `Item` in the `flat_ir.items` vec.
     item_id_to_item_idx: HashMap<ItemId, usize>,
     lifetimes: HashMap<LifetimeId, LifetimeName>,
+    namespace_id_to_number_of_reopened_namespaces: HashMap<ItemId, usize>,
+    reopened_namespace_id_to_idx: HashMap<ItemId, usize>,
 }
 
 impl IR {
@@ -724,6 +751,26 @@
     pub fn get_lifetime(&self, lifetime_id: LifetimeId) -> Option<&LifetimeName> {
         self.lifetimes.get(&lifetime_id)
     }
+
+    pub fn get_reopened_namespace_idx(&self, id: ItemId) -> Result<usize> {
+        Ok(*self.reopened_namespace_id_to_idx.get(&id).with_context(|| {
+            format!("Could not find the reopened namespace index for namespace {:?}.", id)
+        })?)
+    }
+
+    pub fn is_last_reopened_namespace(&self, id: ItemId, canonical_id: ItemId) -> Result<bool> {
+        let idx = self.get_reopened_namespace_idx(id)?;
+        let last_item_idx = self
+            .namespace_id_to_number_of_reopened_namespaces
+            .get(&canonical_id)
+            .with_context(|| {
+            format!(
+                "Could not find number of reopened namespaces for namespace {:?}.",
+                canonical_id
+            )
+        })? - 1;
+        Ok(idx == last_item_idx)
+    }
 }
 
 #[cfg(test)]
diff --git a/rs_bindings_from_cc/ir_from_cc_test.rs b/rs_bindings_from_cc/ir_from_cc_test.rs
index e800748..9bf2a2c 100644
--- a/rs_bindings_from_cc/ir_from_cc_test.rs
+++ b/rs_bindings_from_cc/ir_from_cc_test.rs
@@ -1685,7 +1685,9 @@
     assert_ir_matches!(ir, quote! { TypeAlias { identifier: "MyStruct" ... } });
 }
 
-#[test]
+// TODO(b/214901011): This only worked because we didn't generate bindings for
+// the second reopened namespace.
+// #[test]
 fn test_ignore_struct_typedef_from_decl_context_redecl() {
     let ir = ir_from_cc(
         r#"
@@ -1733,7 +1735,9 @@
     assert_ir_matches!(ir, quote! { TypeAlias { identifier: "MyUnion" ... } });
 }
 
-#[test]
+// TODO(b/214901011): This only worked because we didn't generate bindings for
+// the second reopened namespace.
+// #[test]
 fn test_ignore_union_typedef_from_decl_context_redecl() {
     let ir = ir_from_cc(
         r#"
@@ -2847,14 +2851,118 @@
     );
 
     let namespaces = ir.namespaces().collect_vec();
-    assert_eq!(namespaces.len(), 1);
+    assert_eq!(namespaces.len(), 2);
     assert_eq!(namespaces[0].id, namespaces[0].canonical_namespace_id);
-    // TODO(rosica): We actually need to have 2 namespaces here, but
-    // we currently only generate IR for the canonical decls.
-    // Enable the commented out assertion once we generate IR for all
-    // namespace segments.
-    // assert_eq!(namespaces[0].canonical_namespace_id,
-    // namespaces[1].canonical_namespace_id);
+    assert_eq!(namespaces[0].canonical_namespace_id, namespaces[1].canonical_namespace_id);
+}
+
+#[test]
+fn test_reopened_namespaces() {
+    let ir = ir_from_cc(
+        r#"
+        namespace test_namespace_bindings {
+        namespace inner {}
+        }
+
+        namespace test_namespace_bindings {
+        namespace inner {}
+        }"#,
+    )
+    .unwrap();
+
+    assert_ir_matches!(
+        ir,
+        quote! {
+            ...
+            Namespace(Namespace {
+                name: "test_namespace_bindings" ...
+            })
+            ...
+            Namespace(Namespace {
+              name: "inner" ...
+            })
+            ...
+            Namespace(Namespace {
+              name: "test_namespace_bindings" ...
+            })
+            ...
+            Namespace(Namespace {
+              name: "inner" ...
+            })
+            ...
+        }
+    );
+}
+
+#[test]
+fn test_namespace_stored_data_in_ir() {
+    let ir = ir_from_cc(
+        r#"
+        namespace test_namespace_bindings {
+          namespace inner {}
+        }
+        namespace test_namespace_bindings {
+          namespace inner {}
+          namespace inner {}
+        }"#,
+    )
+    .unwrap();
+
+    let outer_namespaces =
+        ir.namespaces().filter(|ns| ns.name == ir_id("test_namespace_bindings")).collect_vec();
+    assert_eq!(outer_namespaces.len(), 2);
+
+    assert_eq!(ir.get_reopened_namespace_idx(outer_namespaces[0].id).unwrap(), 0);
+    assert_eq!(ir.get_reopened_namespace_idx(outer_namespaces[1].id).unwrap(), 1);
+
+    assert_eq!(
+        ir.is_last_reopened_namespace(
+            outer_namespaces[0].id,
+            outer_namespaces[0].canonical_namespace_id
+        )
+        .unwrap(),
+        false
+    );
+    assert_eq!(
+        ir.is_last_reopened_namespace(
+            outer_namespaces[1].id,
+            outer_namespaces[1].canonical_namespace_id
+        )
+        .unwrap(),
+        true
+    );
+
+    let inner_namespaces = ir.namespaces().filter(|ns| ns.name == ir_id("inner")).collect_vec();
+    assert_eq!(inner_namespaces.len(), 3);
+
+    assert_eq!(ir.get_reopened_namespace_idx(inner_namespaces[0].id).unwrap(), 0);
+    assert_eq!(ir.get_reopened_namespace_idx(inner_namespaces[1].id).unwrap(), 1);
+    assert_eq!(ir.get_reopened_namespace_idx(inner_namespaces[2].id).unwrap(), 2);
+
+    assert_eq!(
+        ir.is_last_reopened_namespace(
+            inner_namespaces[0].id,
+            inner_namespaces[0].canonical_namespace_id
+        )
+        .unwrap(),
+        false
+    );
+    assert_eq!(
+        ir.is_last_reopened_namespace(
+            inner_namespaces[1].id,
+            inner_namespaces[1].canonical_namespace_id
+        )
+        .unwrap(),
+        false
+    );
+    assert_eq!(
+        ir.is_last_reopened_namespace(
+            inner_namespaces[2].id,
+            inner_namespaces[2].canonical_namespace_id
+        )
+        .unwrap(),
+        true
+    );
 }
 
 #[test]
diff --git a/rs_bindings_from_cc/src_code_gen.rs b/rs_bindings_from_cc/src_code_gen.rs
index 556aa7d..e31f458 100644
--- a/rs_bindings_from_cc/src_code_gen.rs
+++ b/rs_bindings_from_cc/src_code_gen.rs
@@ -1487,7 +1487,26 @@
         has_record = has_record || generated.has_record;
     }
 
-    let name = make_rs_ident(&namespace.name.identifier);
+    let reopened_namespace_idx = ir.get_reopened_namespace_idx(namespace.id)?;
+    let should_skip_index =
+        ir.is_last_reopened_namespace(namespace.id, namespace.canonical_namespace_id)?;
+
+    let name = if should_skip_index {
+        make_rs_ident(&namespace.name.identifier)
+    } else {
+        make_rs_ident(&format!("{}_{}", &namespace.name.identifier, reopened_namespace_idx))
+    };
+
+    let use_stmt_for_previous_namespace = if reopened_namespace_idx == 0 {
+        quote! {}
+    } else {
+        let previous_namespace_ident = make_rs_ident(&format!(
+            "{}_{}",
+            &namespace.name.identifier,
+            reopened_namespace_idx - 1
+        ));
+        quote! { pub use super::#previous_namespace_ident::*; __NEWLINE__ __NEWLINE__ }
+    };
 
     let thunks_tokens = quote! {
         #( #thunks )*
@@ -1499,6 +1518,8 @@
 
     let namespace_tokens = quote! {
         pub mod #name {
+            #use_stmt_for_previous_namespace
+
             #( #items __NEWLINE__ __NEWLINE__ )*
         }
     };
@@ -5750,4 +5771,40 @@
         );
         Ok(())
     }
+
+    #[test]
+    fn test_reopened_namespaces() -> Result<()> {
+        let rs_api = generate_bindings_tokens(&ir_from_cc(
+            r#"
+        namespace test_namespace_bindings {
+        namespace inner {}
+        }  // namespace test_namespace_bindings
+
+        namespace test_namespace_bindings {
+        namespace inner {}
+        }  // namespace test_namespace_bindings"#,
+        )?)?
+        .rs_api;
+
+        assert_rs_matches!(
+            rs_api,
+            quote! {
+                ...
+                pub mod test_namespace_bindings_0 {
+                    pub mod inner_0 {} ...
+                }
+                ...
+                pub mod test_namespace_bindings {
+                    pub use super::test_namespace_bindings_0::*;
+                    ...
+                    pub mod inner {
+                        pub use super::inner_0::*;
+                        ...
+                    }
+                }
+                ...
+            }
+        );
+        Ok(())
+    }
 }
diff --git a/rs_bindings_from_cc/test/golden/namespace_rs_api.rs b/rs_bindings_from_cc/test/golden/namespace_rs_api.rs
index 59267ec..6ff0900 100644
--- a/rs_bindings_from_cc/test/golden/namespace_rs_api.rs
+++ b/rs_bindings_from_cc/test/golden/namespace_rs_api.rs
@@ -71,13 +71,13 @@
     unsafe { crate::detail::__rust_thunk___Z8identityN23test_namespace_bindings1SE(s) }
 }
 
-pub mod test_namespace_bindings_reopened {
+pub mod test_namespace_bindings_reopened_0 {
     #[inline(always)]
     pub fn x() {
         unsafe { crate::detail::__rust_thunk___ZN32test_namespace_bindings_reopened1xEv() }
     }
 
-    pub mod inner {
+    pub mod inner_0 {
         #[ctor::recursively_pinned]
         #[repr(C)]
         pub struct S {
@@ -114,7 +114,29 @@
 
 // namespace test_namespace_bindings_reopened
 
-// namespace inner
+pub mod test_namespace_bindings_reopened {
+    pub use super::test_namespace_bindings_reopened_0::*;
+
+    #[inline(always)]
+    pub fn y() {
+        unsafe { crate::detail::__rust_thunk___ZN32test_namespace_bindings_reopened1yEv() }
+    }
+
+    pub mod inner {
+        pub use super::inner_0::*;
+
+        #[inline(always)]
+        pub fn z(s: crate::test_namespace_bindings_reopened::inner::S) {
+            unsafe {
+                crate::detail::__rust_thunk___ZN32test_namespace_bindings_reopened5inner1zENS0_1SE(
+                    s,
+                )
+            }
+        }
+    }
+
+    // namespace inner
+}
 
 // namespace test_namespace_bindings_reopened
 
@@ -136,6 +158,12 @@
         ) -> crate::test_namespace_bindings::S;
         #[link_name = "_ZN32test_namespace_bindings_reopened1xEv"]
         pub(crate) fn __rust_thunk___ZN32test_namespace_bindings_reopened1xEv();
+        #[link_name = "_ZN32test_namespace_bindings_reopened1yEv"]
+        pub(crate) fn __rust_thunk___ZN32test_namespace_bindings_reopened1yEv();
+        #[link_name = "_ZN32test_namespace_bindings_reopened5inner1zENS0_1SE"]
+        pub(crate) fn __rust_thunk___ZN32test_namespace_bindings_reopened5inner1zENS0_1SE(
+            s: crate::test_namespace_bindings_reopened::inner::S,
+        );
     }
 }