blob: 7547c7cdd076ce1541858460baaab2186981aeb7 [file] [log] [blame]
Brian Silverman4e662aa2022-05-11 23:10:19 -07001// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use indexmap::map::IndexMap as HashMap;
10
11use syn::Ident;
12
13use crate::{
14 conversion::{
15 api::{Api, SubclassName},
16 apivec::ApiVec,
17 error_reporter::convert_item_apis,
18 ConvertError,
19 },
20 types::{validate_ident_ok_for_cxx, QualifiedName},
21};
22
23use super::fun::FnPhase;
24
25/// Do some final checks that the names we've come up with can be represented
26/// within cxx.
27pub(crate) fn check_names(apis: ApiVec<FnPhase>) -> ApiVec<FnPhase> {
28 // If any items have names which can't be represented by cxx,
29 // abort. This check should ideally be done at the times we fill in the
30 // `name` field of each `api` in the first place, at parse time, though
31 // as the `name` field of each API may change during various analysis phases,
32 // currently it seems better to do it here to ensure we respect
33 // the output of any such changes.
34 let mut intermediate = ApiVec::new();
35 convert_item_apis(apis, &mut intermediate, |api| match api {
36 Api::Typedef { ref name, .. }
37 | Api::ForwardDeclaration { ref name, .. }
38 | Api::OpaqueTypedef { ref name, .. }
39 | Api::Const { ref name, .. }
40 | Api::Enum { ref name, .. }
41 | Api::Struct { ref name, .. } => {
42 validate_all_segments_ok_for_cxx(name.name.segment_iter())?;
43 if let Some(cpp_name) = name.cpp_name_if_present() {
44 // The C++ name might itself be outer_type::inner_type and thus may
45 // have multiple segments.
46 validate_all_segments_ok_for_cxx(
47 QualifiedName::new_from_cpp_name(cpp_name).segment_iter(),
48 )?;
49 }
50 Ok(Box::new(std::iter::once(api)))
51 }
52 Api::Subclass {
53 name: SubclassName(ref name),
54 ref superclass,
55 } => {
56 validate_all_segments_ok_for_cxx(name.name.segment_iter())?;
57 validate_all_segments_ok_for_cxx(superclass.segment_iter())?;
58 Ok(Box::new(std::iter::once(api)))
59 }
60 Api::Function { ref name, .. } => {
61 // we don't handle function names here because
62 // the function analysis does an equivalent check. Instead of just rejecting
63 // the function, it creates a wrapper function instead with a more
64 // palatable name. That's preferable to rejecting the API entirely.
65 validate_all_segments_ok_for_cxx(name.name.segment_iter())?;
66 Ok(Box::new(std::iter::once(api)))
67 }
68 Api::ConcreteType { .. }
69 | Api::CType { .. }
70 | Api::StringConstructor { .. }
71 | Api::RustType { .. }
72 | Api::RustSubclassFn { .. }
73 | Api::RustFn { .. }
74 | Api::SubclassTraitItem { .. }
75 | Api::ExternCppType { .. }
76 | Api::IgnoredItem { .. } => Ok(Box::new(std::iter::once(api))),
77 });
78
79 // Reject any names which are duplicates within the cxx bridge mod,
80 // that has a flat namespace.
81 let mut names_found: HashMap<Ident, Vec<String>> = HashMap::new();
82 for api in intermediate.iter() {
83 let my_name = api.cxxbridge_name();
84 if let Some(name) = my_name {
85 let e = names_found.entry(name).or_default();
86 e.push(api.name_info().name.to_string());
87 }
88 }
89 let mut results = ApiVec::new();
90 convert_item_apis(intermediate, &mut results, |api| {
91 let my_name = api.cxxbridge_name();
92 if let Some(name) = my_name {
93 let symbols_for_this_name = names_found.entry(name).or_default();
94 if symbols_for_this_name.len() > 1usize {
95 Err(ConvertError::DuplicateCxxBridgeName(
96 symbols_for_this_name.clone(),
97 ))
98 } else {
99 Ok(Box::new(std::iter::once(api)))
100 }
101 } else {
102 Ok(Box::new(std::iter::once(api)))
103 }
104 });
105 results
106}
107
108fn validate_all_segments_ok_for_cxx(
109 items: impl Iterator<Item = String>,
110) -> Result<(), ConvertError> {
111 for seg in items {
112 validate_ident_ok_for_cxx(&seg)?;
113 }
114 Ok(())
115}