blob: 6f245c22c0212d7495160913035dfca549010811 [file] [log] [blame]
Brian Silverman4e662aa2022-05-11 23:10:19 -07001// Copyright 2020 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 syn::{
10 parse_quote, punctuated::Punctuated, FnArg, GenericArgument, PathArguments, PathSegment,
11 ReturnType, Token, Type, TypePath,
12};
13
14/// Mod to handle stripping paths off the front of types.
15
16fn unqualify_type_path(typ: TypePath) -> TypePath {
17 // If we've still got more than one
18 // path segment then this is referring to a type within
19 // C++ namespaces. Strip them off for now, until cxx supports
20 // nested mods within a cxx::bridge.
21 // This is 'safe' because earlier code will already have
22 // failed with 'DuplicateType' if we had several types called
23 // the same thing.
24 let last_seg = typ.path.segments.into_iter().last().unwrap();
25 let ident = &last_seg.ident;
26 let args = match last_seg.arguments {
27 PathArguments::AngleBracketed(mut ab) => {
28 ab.args = unqualify_punctuated(ab.args);
29 PathArguments::AngleBracketed(ab)
30 }
31 _ => last_seg.arguments.clone(),
32 };
33 let last_seg: PathSegment = parse_quote!( #ident #args );
34 parse_quote!(
35 #last_seg
36 )
37}
38
39fn unqualify_punctuated<P>(pun: Punctuated<GenericArgument, P>) -> Punctuated<GenericArgument, P>
40where
41 P: Default,
42{
43 let mut new_pun = Punctuated::new();
44 for arg in pun.into_iter() {
45 new_pun.push(match arg {
46 GenericArgument::Type(t) => GenericArgument::Type(unqualify_type(t)),
47 _ => arg,
48 });
49 }
50 new_pun
51}
52
53fn unqualify_type(typ: Type) -> Type {
54 match typ {
55 Type::Path(typ) => Type::Path(unqualify_type_path(typ)),
56 Type::Reference(mut typeref) => {
57 typeref.elem = unqualify_boxed_type(typeref.elem);
58 Type::Reference(typeref)
59 }
60 Type::Ptr(mut typeptr) => {
61 typeptr.elem = unqualify_boxed_type(typeptr.elem);
62 Type::Ptr(typeptr)
63 }
64 _ => typ,
65 }
66}
67
68fn unqualify_boxed_type(typ: Box<Type>) -> Box<Type> {
69 Box::new(unqualify_type(*typ))
70}
71
72pub(crate) fn unqualify_ret_type(ret_type: ReturnType) -> ReturnType {
73 match ret_type {
74 ReturnType::Type(tok, boxed_type) => {
75 ReturnType::Type(tok, unqualify_boxed_type(boxed_type))
76 }
77 _ => ret_type,
78 }
79}
80
81pub(crate) fn unqualify_params(
82 params: Punctuated<FnArg, Token![,]>,
83) -> Punctuated<FnArg, Token![,]> {
84 params
85 .into_iter()
86 .map(|p| match p {
87 FnArg::Typed(mut pt) => {
88 pt.ty = unqualify_boxed_type(pt.ty);
89 FnArg::Typed(pt)
90 }
91 _ => p,
92 })
93 .collect()
94}