mirror of
https://gitee.com/openharmony/third_party_rust_cxx
synced 2024-11-27 01:11:38 +00:00
Add ForeignName wrapper around non-Rust names
This commit is contained in:
parent
9f84fe8bbd
commit
ed6ba4a63c
@ -53,7 +53,7 @@ mod tests {
|
||||
use super::NamespaceEntries;
|
||||
use crate::syntax::attrs::OtherAttrs;
|
||||
use crate::syntax::namespace::Namespace;
|
||||
use crate::syntax::{Api, Doc, ExternType, Lang, Lifetimes, Pair};
|
||||
use crate::syntax::{Api, Doc, ExternType, ForeignName, Lang, Lifetimes, Pair};
|
||||
use proc_macro2::{Ident, Span};
|
||||
use std::iter::FromIterator;
|
||||
use syn::punctuated::Punctuated;
|
||||
@ -119,7 +119,7 @@ mod tests {
|
||||
|
||||
fn assert_ident(api: &Api, expected: &str) {
|
||||
if let Api::CxxType(cxx_type) = api {
|
||||
assert_eq!(cxx_type.name.cxx, expected);
|
||||
assert_eq!(cxx_type.name.cxx.to_string(), expected);
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
@ -127,7 +127,6 @@ mod tests {
|
||||
|
||||
fn make_api(ns: Option<&str>, ident: &str) -> Api {
|
||||
let ns = ns.map_or(Namespace::ROOT, |ns| syn::parse_str(ns).unwrap());
|
||||
let ident = Ident::new(ident, Span::call_site());
|
||||
Api::CxxType(ExternType {
|
||||
lang: Lang::Rust,
|
||||
doc: Doc::new(),
|
||||
@ -137,8 +136,8 @@ mod tests {
|
||||
type_token: Token![type](Span::call_site()),
|
||||
name: Pair {
|
||||
namespace: ns,
|
||||
cxx: ident.clone(),
|
||||
rust: ident,
|
||||
cxx: ForeignName::parse(ident, Span::call_site()).unwrap(),
|
||||
rust: Ident::new(ident, Span::call_site()),
|
||||
},
|
||||
generics: Lifetimes {
|
||||
lt_token: None,
|
||||
|
@ -50,10 +50,10 @@ fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
|
||||
for api in apis {
|
||||
write!(out, "{:1$}", "", indent);
|
||||
match api {
|
||||
Api::Struct(strct) => write_struct_decl(out, &strct.name.cxx),
|
||||
Api::Struct(strct) => write_struct_decl(out, &strct.name),
|
||||
Api::Enum(enm) => write_enum_decl(out, enm),
|
||||
Api::CxxType(ety) => write_struct_using(out, &ety.name),
|
||||
Api::RustType(ety) => write_struct_decl(out, &ety.name.cxx),
|
||||
Api::RustType(ety) => write_struct_decl(out, &ety.name),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
@ -296,8 +296,8 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
|
||||
writeln!(out, "#endif // {}", guard);
|
||||
}
|
||||
|
||||
fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
|
||||
writeln!(out, "struct {};", ident);
|
||||
fn write_struct_decl(out: &mut OutFile, ident: &Pair) {
|
||||
writeln!(out, "struct {};", ident.cxx);
|
||||
}
|
||||
|
||||
fn write_enum_decl(out: &mut OutFile, enm: &Enum) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::syntax::namespace::Namespace;
|
||||
use crate::syntax::report::Errors;
|
||||
use crate::syntax::Atom::{self, *};
|
||||
use crate::syntax::{Derive, Doc};
|
||||
use crate::syntax::{Derive, Doc, ForeignName};
|
||||
use proc_macro2::{Ident, TokenStream};
|
||||
use quote::ToTokens;
|
||||
use syn::parse::{ParseStream, Parser as _};
|
||||
@ -31,7 +31,7 @@ pub struct Parser<'a> {
|
||||
pub derives: Option<&'a mut Vec<Derive>>,
|
||||
pub repr: Option<&'a mut Option<Atom>>,
|
||||
pub namespace: Option<&'a mut Namespace>,
|
||||
pub cxx_name: Option<&'a mut Option<Ident>>,
|
||||
pub cxx_name: Option<&'a mut Option<ForeignName>>,
|
||||
pub rust_name: Option<&'a mut Option<Ident>>,
|
||||
|
||||
// Suppress clippy needless_update lint ("struct update has no effect, all
|
||||
@ -96,7 +96,7 @@ pub fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> Othe
|
||||
}
|
||||
}
|
||||
} else if attr.path.is_ident("cxx_name") {
|
||||
match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
|
||||
match parse_cxx_name_attribute.parse2(attr.tokens.clone()) {
|
||||
Ok(attr) => {
|
||||
if let Some(cxx_name) = &mut parser.cxx_name {
|
||||
**cxx_name = Some(attr);
|
||||
@ -109,7 +109,7 @@ pub fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> Othe
|
||||
}
|
||||
}
|
||||
} else if attr.path.is_ident("rust_name") {
|
||||
match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
|
||||
match parse_rust_name_attribute.parse2(attr.tokens.clone()) {
|
||||
Ok(attr) => {
|
||||
if let Some(rust_name) = &mut parser.rust_name {
|
||||
**rust_name = Some(attr);
|
||||
@ -192,7 +192,18 @@ fn parse_namespace_attribute(input: ParseStream) -> Result<Namespace> {
|
||||
Ok(namespace)
|
||||
}
|
||||
|
||||
fn parse_function_alias_attribute(input: ParseStream) -> Result<Ident> {
|
||||
fn parse_cxx_name_attribute(input: ParseStream) -> Result<ForeignName> {
|
||||
input.parse::<Token![=]>()?;
|
||||
if input.peek(LitStr) {
|
||||
let lit: LitStr = input.parse()?;
|
||||
ForeignName::parse(&lit.value(), lit.span())
|
||||
} else {
|
||||
let ident: Ident = input.parse()?;
|
||||
ForeignName::parse(&ident.to_string(), ident.span())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_rust_name_attribute(input: ParseStream) -> Result<Ident> {
|
||||
input.parse::<Token![=]>()?;
|
||||
if input.peek(LitStr) {
|
||||
let lit: LitStr = input.parse()?;
|
||||
|
@ -1,27 +1,24 @@
|
||||
use crate::syntax::check::Check;
|
||||
use crate::syntax::{error, Api, Pair};
|
||||
use proc_macro2::Ident;
|
||||
|
||||
fn check(cx: &mut Check, name: &Pair) {
|
||||
for segment in &name.namespace {
|
||||
check_cxx_ident(cx, segment);
|
||||
check_cxx_ident(cx, &segment.to_string());
|
||||
}
|
||||
check_cxx_ident(cx, &name.cxx);
|
||||
check_rust_ident(cx, &name.rust);
|
||||
check_cxx_ident(cx, &name.cxx.to_string());
|
||||
check_rust_ident(cx, &name.rust.to_string());
|
||||
|
||||
fn check_cxx_ident(cx: &mut Check, ident: &Ident) {
|
||||
let s = ident.to_string();
|
||||
if s.starts_with("cxxbridge") {
|
||||
fn check_cxx_ident(cx: &mut Check, ident: &str) {
|
||||
if ident.starts_with("cxxbridge") {
|
||||
cx.error(ident, error::CXXBRIDGE_RESERVED.msg);
|
||||
}
|
||||
if s.contains("__") {
|
||||
if ident.contains("__") {
|
||||
cx.error(ident, error::DOUBLE_UNDERSCORE.msg);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_rust_ident(cx: &mut Check, ident: &Ident) {
|
||||
let s = ident.to_string();
|
||||
if s.starts_with("cxxbridge") {
|
||||
fn check_rust_ident(cx: &mut Check, ident: &str) {
|
||||
if ident.starts_with("cxxbridge") {
|
||||
cx.error(ident, error::CXXBRIDGE_RESERVED.msg);
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ use syn::{Expr, Generics, Lifetime, LitInt, Token, Type as RustType};
|
||||
pub use self::atom::Atom;
|
||||
pub use self::derive::{Derive, Trait};
|
||||
pub use self::doc::Doc;
|
||||
pub use self::names::ForeignName;
|
||||
pub use self::parse::parse_items;
|
||||
pub use self::types::Types;
|
||||
|
||||
@ -252,7 +253,7 @@ pub enum Lang {
|
||||
#[derive(Clone)]
|
||||
pub struct Pair {
|
||||
pub namespace: Namespace,
|
||||
pub cxx: Ident,
|
||||
pub cxx: ForeignName,
|
||||
pub rust: Ident,
|
||||
}
|
||||
|
||||
|
@ -1,25 +1,37 @@
|
||||
use crate::syntax::symbol::Segment;
|
||||
use crate::syntax::{Lifetimes, NamedType, Pair, Symbol};
|
||||
use proc_macro2::{Ident, Span};
|
||||
use std::fmt::{self, Display};
|
||||
use std::iter;
|
||||
use syn::parse::Result;
|
||||
use syn::punctuated::Punctuated;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ForeignName {
|
||||
text: String,
|
||||
span: Span,
|
||||
}
|
||||
|
||||
impl Pair {
|
||||
pub fn to_symbol(&self) -> Symbol {
|
||||
Symbol::from_idents(self.iter_all_segments())
|
||||
let segments = self
|
||||
.namespace
|
||||
.iter()
|
||||
.map(|ident| ident as &dyn Segment)
|
||||
.chain(iter::once(&self.cxx as &dyn Segment));
|
||||
Symbol::from_idents(segments)
|
||||
}
|
||||
|
||||
pub fn to_fully_qualified(&self) -> String {
|
||||
let mut fully_qualified = String::new();
|
||||
for segment in self.iter_all_segments() {
|
||||
for segment in &self.namespace {
|
||||
fully_qualified += "::";
|
||||
fully_qualified += &segment.to_string();
|
||||
}
|
||||
fully_qualified += "::";
|
||||
fully_qualified += &self.cxx.to_string();
|
||||
fully_qualified
|
||||
}
|
||||
|
||||
fn iter_all_segments(&self) -> impl Iterator<Item = &Ident> {
|
||||
self.namespace.iter().chain(iter::once(&self.cxx))
|
||||
}
|
||||
}
|
||||
|
||||
impl NamedType {
|
||||
@ -36,3 +48,19 @@ impl NamedType {
|
||||
self.rust.span()
|
||||
}
|
||||
}
|
||||
|
||||
impl ForeignName {
|
||||
pub fn parse(text: &str, span: Span) -> Result<Self> {
|
||||
// TODO: support C++ names containing whitespace (`unsigned int`) or
|
||||
// non-alphanumeric characters (`operator++`).
|
||||
let ident: Ident = syn::parse_str(text)?;
|
||||
let text = ident.to_string();
|
||||
Ok(ForeignName { text, span })
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ForeignName {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str(&self.text)
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,9 @@ use crate::syntax::file::{Item, ItemForeignMod};
|
||||
use crate::syntax::report::Errors;
|
||||
use crate::syntax::Atom::*;
|
||||
use crate::syntax::{
|
||||
attrs, error, Api, Array, Derive, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind,
|
||||
Lang, Lifetimes, NamedType, Namespace, Pair, Receiver, Ref, Signature, SliceRef, Struct, Ty1,
|
||||
Type, TypeAlias, Var, Variant,
|
||||
attrs, error, Api, Array, Derive, Doc, Enum, ExternFn, ExternType, ForeignName, Impl, Include,
|
||||
IncludeKind, Lang, Lifetimes, NamedType, Namespace, Pair, Receiver, Ref, Signature, SliceRef,
|
||||
Struct, Ty1, Type, TypeAlias, Var, Variant,
|
||||
};
|
||||
use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
|
||||
use quote::{format_ident, quote, quote_spanned};
|
||||
@ -1258,11 +1258,16 @@ fn visibility_pub(vis: &Visibility, inherited: &Ident) -> Token![pub] {
|
||||
})
|
||||
}
|
||||
|
||||
fn pair(namespace: Namespace, default: &Ident, cxx: Option<Ident>, rust: Option<Ident>) -> Pair {
|
||||
let default = || default.clone();
|
||||
fn pair(
|
||||
namespace: Namespace,
|
||||
default: &Ident,
|
||||
cxx: Option<ForeignName>,
|
||||
rust: Option<Ident>,
|
||||
) -> Pair {
|
||||
Pair {
|
||||
namespace,
|
||||
cxx: cxx.unwrap_or_else(default),
|
||||
rust: rust.unwrap_or_else(default),
|
||||
cxx: cxx
|
||||
.unwrap_or_else(|| ForeignName::parse(&default.to_string(), default.span()).unwrap()),
|
||||
rust: rust.unwrap_or_else(|| default.clone()),
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::syntax::namespace::Namespace;
|
||||
use crate::syntax::Pair;
|
||||
use crate::syntax::{ForeignName, Pair};
|
||||
use proc_macro2::{Ident, TokenStream};
|
||||
use quote::ToTokens;
|
||||
use std::fmt::{self, Display, Write};
|
||||
@ -30,7 +30,7 @@ impl Symbol {
|
||||
assert!(self.0.len() > len_before);
|
||||
}
|
||||
|
||||
pub fn from_idents<'a, T: Iterator<Item = &'a Ident>>(it: T) -> Self {
|
||||
pub fn from_idents<'a>(it: impl Iterator<Item = &'a dyn Segment>) -> Self {
|
||||
let mut symbol = Symbol(String::new());
|
||||
for segment in it {
|
||||
segment.write(&mut symbol);
|
||||
@ -55,16 +55,19 @@ impl Segment for str {
|
||||
symbol.push(&self);
|
||||
}
|
||||
}
|
||||
|
||||
impl Segment for usize {
|
||||
fn write(&self, symbol: &mut Symbol) {
|
||||
symbol.push(&self);
|
||||
}
|
||||
}
|
||||
|
||||
impl Segment for Ident {
|
||||
fn write(&self, symbol: &mut Symbol) {
|
||||
symbol.push(&self);
|
||||
}
|
||||
}
|
||||
|
||||
impl Segment for Symbol {
|
||||
fn write(&self, symbol: &mut Symbol) {
|
||||
symbol.push(&self);
|
||||
@ -86,6 +89,14 @@ impl Segment for Pair {
|
||||
}
|
||||
}
|
||||
|
||||
impl Segment for ForeignName {
|
||||
fn write(&self, symbol: &mut Symbol) {
|
||||
// TODO: support C++ names containing whitespace (`unsigned int`) or
|
||||
// non-alphanumeric characters (`operator++`).
|
||||
self.to_string().write(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Segment for &'_ T
|
||||
where
|
||||
T: ?Sized + Segment + Display,
|
||||
|
Loading…
Reference in New Issue
Block a user