mirror of
https://github.com/topjohnwu/cxx.git
synced 2025-02-21 16:41:01 +00:00
Merge pull request #633 from dtolnay/foreign
Add ForeignName wrapper around non-Rust names
This commit is contained in:
commit
010b5c3c25
@ -53,7 +53,7 @@ mod tests {
|
|||||||
use super::NamespaceEntries;
|
use super::NamespaceEntries;
|
||||||
use crate::syntax::attrs::OtherAttrs;
|
use crate::syntax::attrs::OtherAttrs;
|
||||||
use crate::syntax::namespace::Namespace;
|
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 proc_macro2::{Ident, Span};
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use syn::punctuated::Punctuated;
|
use syn::punctuated::Punctuated;
|
||||||
@ -119,7 +119,7 @@ mod tests {
|
|||||||
|
|
||||||
fn assert_ident(api: &Api, expected: &str) {
|
fn assert_ident(api: &Api, expected: &str) {
|
||||||
if let Api::CxxType(cxx_type) = api {
|
if let Api::CxxType(cxx_type) = api {
|
||||||
assert_eq!(cxx_type.name.cxx, expected);
|
assert_eq!(cxx_type.name.cxx.to_string(), expected);
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@ -127,7 +127,6 @@ mod tests {
|
|||||||
|
|
||||||
fn make_api(ns: Option<&str>, ident: &str) -> Api {
|
fn make_api(ns: Option<&str>, ident: &str) -> Api {
|
||||||
let ns = ns.map_or(Namespace::ROOT, |ns| syn::parse_str(ns).unwrap());
|
let ns = ns.map_or(Namespace::ROOT, |ns| syn::parse_str(ns).unwrap());
|
||||||
let ident = Ident::new(ident, Span::call_site());
|
|
||||||
Api::CxxType(ExternType {
|
Api::CxxType(ExternType {
|
||||||
lang: Lang::Rust,
|
lang: Lang::Rust,
|
||||||
doc: Doc::new(),
|
doc: Doc::new(),
|
||||||
@ -137,8 +136,8 @@ mod tests {
|
|||||||
type_token: Token),
|
type_token: Token),
|
||||||
name: Pair {
|
name: Pair {
|
||||||
namespace: ns,
|
namespace: ns,
|
||||||
cxx: ident.clone(),
|
cxx: ForeignName::parse(ident, Span::call_site()).unwrap(),
|
||||||
rust: ident,
|
rust: Ident::new(ident, Span::call_site()),
|
||||||
},
|
},
|
||||||
generics: Lifetimes {
|
generics: Lifetimes {
|
||||||
lt_token: None,
|
lt_token: None,
|
||||||
|
@ -50,10 +50,10 @@ fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
|
|||||||
for api in apis {
|
for api in apis {
|
||||||
write!(out, "{:1$}", "", indent);
|
write!(out, "{:1$}", "", indent);
|
||||||
match api {
|
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::Enum(enm) => write_enum_decl(out, enm),
|
||||||
Api::CxxType(ety) => write_struct_using(out, &ety.name),
|
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!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -296,8 +296,8 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
|
|||||||
writeln!(out, "#endif // {}", guard);
|
writeln!(out, "#endif // {}", guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
|
fn write_struct_decl(out: &mut OutFile, ident: &Pair) {
|
||||||
writeln!(out, "struct {};", ident);
|
writeln!(out, "struct {};", ident.cxx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_enum_decl(out: &mut OutFile, enm: &Enum) {
|
fn write_enum_decl(out: &mut OutFile, enm: &Enum) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::syntax::namespace::Namespace;
|
use crate::syntax::namespace::Namespace;
|
||||||
use crate::syntax::report::Errors;
|
use crate::syntax::report::Errors;
|
||||||
use crate::syntax::Atom::{self, *};
|
use crate::syntax::Atom::{self, *};
|
||||||
use crate::syntax::{Derive, Doc};
|
use crate::syntax::{Derive, Doc, ForeignName};
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
use syn::parse::{ParseStream, Parser as _};
|
use syn::parse::{ParseStream, Parser as _};
|
||||||
@ -31,7 +31,7 @@ pub struct Parser<'a> {
|
|||||||
pub derives: Option<&'a mut Vec<Derive>>,
|
pub derives: Option<&'a mut Vec<Derive>>,
|
||||||
pub repr: Option<&'a mut Option<Atom>>,
|
pub repr: Option<&'a mut Option<Atom>>,
|
||||||
pub namespace: Option<&'a mut Namespace>,
|
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>>,
|
pub rust_name: Option<&'a mut Option<Ident>>,
|
||||||
|
|
||||||
// Suppress clippy needless_update lint ("struct update has no effect, all
|
// 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") {
|
} 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) => {
|
Ok(attr) => {
|
||||||
if let Some(cxx_name) = &mut parser.cxx_name {
|
if let Some(cxx_name) = &mut parser.cxx_name {
|
||||||
**cxx_name = Some(attr);
|
**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") {
|
} 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) => {
|
Ok(attr) => {
|
||||||
if let Some(rust_name) = &mut parser.rust_name {
|
if let Some(rust_name) = &mut parser.rust_name {
|
||||||
**rust_name = Some(attr);
|
**rust_name = Some(attr);
|
||||||
@ -192,7 +192,18 @@ fn parse_namespace_attribute(input: ParseStream) -> Result<Namespace> {
|
|||||||
Ok(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![=]>()?;
|
input.parse::<Token![=]>()?;
|
||||||
if input.peek(LitStr) {
|
if input.peek(LitStr) {
|
||||||
let lit: LitStr = input.parse()?;
|
let lit: LitStr = input.parse()?;
|
||||||
|
@ -1,27 +1,24 @@
|
|||||||
use crate::syntax::check::Check;
|
use crate::syntax::check::Check;
|
||||||
use crate::syntax::{error, Api, Pair};
|
use crate::syntax::{error, Api, Pair};
|
||||||
use proc_macro2::Ident;
|
|
||||||
|
|
||||||
fn check(cx: &mut Check, name: &Pair) {
|
fn check(cx: &mut Check, name: &Pair) {
|
||||||
for segment in &name.namespace {
|
for segment in &name.namespace {
|
||||||
check_cxx_ident(cx, segment);
|
check_cxx_ident(cx, &segment.to_string());
|
||||||
}
|
}
|
||||||
check_cxx_ident(cx, &name.cxx);
|
check_cxx_ident(cx, &name.cxx.to_string());
|
||||||
check_rust_ident(cx, &name.rust);
|
check_rust_ident(cx, &name.rust.to_string());
|
||||||
|
|
||||||
fn check_cxx_ident(cx: &mut Check, ident: &Ident) {
|
fn check_cxx_ident(cx: &mut Check, ident: &str) {
|
||||||
let s = ident.to_string();
|
if ident.starts_with("cxxbridge") {
|
||||||
if s.starts_with("cxxbridge") {
|
|
||||||
cx.error(ident, error::CXXBRIDGE_RESERVED.msg);
|
cx.error(ident, error::CXXBRIDGE_RESERVED.msg);
|
||||||
}
|
}
|
||||||
if s.contains("__") {
|
if ident.contains("__") {
|
||||||
cx.error(ident, error::DOUBLE_UNDERSCORE.msg);
|
cx.error(ident, error::DOUBLE_UNDERSCORE.msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_rust_ident(cx: &mut Check, ident: &Ident) {
|
fn check_rust_ident(cx: &mut Check, ident: &str) {
|
||||||
let s = ident.to_string();
|
if ident.starts_with("cxxbridge") {
|
||||||
if s.starts_with("cxxbridge") {
|
|
||||||
cx.error(ident, error::CXXBRIDGE_RESERVED.msg);
|
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::atom::Atom;
|
||||||
pub use self::derive::{Derive, Trait};
|
pub use self::derive::{Derive, Trait};
|
||||||
pub use self::doc::Doc;
|
pub use self::doc::Doc;
|
||||||
|
pub use self::names::ForeignName;
|
||||||
pub use self::parse::parse_items;
|
pub use self::parse::parse_items;
|
||||||
pub use self::types::Types;
|
pub use self::types::Types;
|
||||||
|
|
||||||
@ -252,7 +253,7 @@ pub enum Lang {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Pair {
|
pub struct Pair {
|
||||||
pub namespace: Namespace,
|
pub namespace: Namespace,
|
||||||
pub cxx: Ident,
|
pub cxx: ForeignName,
|
||||||
pub rust: Ident,
|
pub rust: Ident,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,25 +1,37 @@
|
|||||||
|
use crate::syntax::symbol::Segment;
|
||||||
use crate::syntax::{Lifetimes, NamedType, Pair, Symbol};
|
use crate::syntax::{Lifetimes, NamedType, Pair, Symbol};
|
||||||
use proc_macro2::{Ident, Span};
|
use proc_macro2::{Ident, Span};
|
||||||
|
use std::fmt::{self, Display};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
use syn::parse::Result;
|
||||||
use syn::punctuated::Punctuated;
|
use syn::punctuated::Punctuated;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ForeignName {
|
||||||
|
text: String,
|
||||||
|
span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
impl Pair {
|
impl Pair {
|
||||||
pub fn to_symbol(&self) -> Symbol {
|
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 {
|
pub fn to_fully_qualified(&self) -> String {
|
||||||
let mut fully_qualified = String::new();
|
let mut fully_qualified = String::new();
|
||||||
for segment in self.iter_all_segments() {
|
for segment in &self.namespace {
|
||||||
fully_qualified += "::";
|
fully_qualified += "::";
|
||||||
fully_qualified += &segment.to_string();
|
fully_qualified += &segment.to_string();
|
||||||
}
|
}
|
||||||
|
fully_qualified += "::";
|
||||||
|
fully_qualified += &self.cxx.to_string();
|
||||||
fully_qualified
|
fully_qualified
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iter_all_segments(&self) -> impl Iterator<Item = &Ident> {
|
|
||||||
self.namespace.iter().chain(iter::once(&self.cxx))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NamedType {
|
impl NamedType {
|
||||||
@ -36,3 +48,19 @@ impl NamedType {
|
|||||||
self.rust.span()
|
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::report::Errors;
|
||||||
use crate::syntax::Atom::*;
|
use crate::syntax::Atom::*;
|
||||||
use crate::syntax::{
|
use crate::syntax::{
|
||||||
attrs, error, Api, Array, Derive, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind,
|
attrs, error, Api, Array, Derive, Doc, Enum, ExternFn, ExternType, ForeignName, Impl, Include,
|
||||||
Lang, Lifetimes, NamedType, Namespace, Pair, Receiver, Ref, Signature, SliceRef, Struct, Ty1,
|
IncludeKind, Lang, Lifetimes, NamedType, Namespace, Pair, Receiver, Ref, Signature, SliceRef,
|
||||||
Type, TypeAlias, Var, Variant,
|
Struct, Ty1, Type, TypeAlias, Var, Variant,
|
||||||
};
|
};
|
||||||
use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
|
use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
|
||||||
use quote::{format_ident, quote, quote_spanned};
|
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 {
|
fn pair(
|
||||||
let default = || default.clone();
|
namespace: Namespace,
|
||||||
|
default: &Ident,
|
||||||
|
cxx: Option<ForeignName>,
|
||||||
|
rust: Option<Ident>,
|
||||||
|
) -> Pair {
|
||||||
Pair {
|
Pair {
|
||||||
namespace,
|
namespace,
|
||||||
cxx: cxx.unwrap_or_else(default),
|
cxx: cxx
|
||||||
rust: rust.unwrap_or_else(default),
|
.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::namespace::Namespace;
|
||||||
use crate::syntax::Pair;
|
use crate::syntax::{ForeignName, Pair};
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
use std::fmt::{self, Display, Write};
|
use std::fmt::{self, Display, Write};
|
||||||
@ -30,7 +30,7 @@ impl Symbol {
|
|||||||
assert!(self.0.len() > len_before);
|
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());
|
let mut symbol = Symbol(String::new());
|
||||||
for segment in it {
|
for segment in it {
|
||||||
segment.write(&mut symbol);
|
segment.write(&mut symbol);
|
||||||
@ -55,16 +55,19 @@ impl Segment for str {
|
|||||||
symbol.push(&self);
|
symbol.push(&self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Segment for usize {
|
impl Segment for usize {
|
||||||
fn write(&self, symbol: &mut Symbol) {
|
fn write(&self, symbol: &mut Symbol) {
|
||||||
symbol.push(&self);
|
symbol.push(&self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Segment for Ident {
|
impl Segment for Ident {
|
||||||
fn write(&self, symbol: &mut Symbol) {
|
fn write(&self, symbol: &mut Symbol) {
|
||||||
symbol.push(&self);
|
symbol.push(&self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Segment for Symbol {
|
impl Segment for Symbol {
|
||||||
fn write(&self, symbol: &mut Symbol) {
|
fn write(&self, symbol: &mut Symbol) {
|
||||||
symbol.push(&self);
|
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
|
impl<T> Segment for &'_ T
|
||||||
where
|
where
|
||||||
T: ?Sized + Segment + Display,
|
T: ?Sized + Segment + Display,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user