Data structure to represent possibly unsafe module

This commit is contained in:
David Tolnay 2020-08-29 11:27:05 -07:00
parent 5e668bce9b
commit 05ef6ffa28
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
4 changed files with 59 additions and 11 deletions

View File

@ -1,21 +1,20 @@
use crate::syntax::atom::Atom::{self, *};
use crate::syntax::file::Module;
use crate::syntax::namespace::Namespace;
use crate::syntax::report::Errors;
use crate::syntax::symbol::Symbol;
use crate::syntax::{
self, check, mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, TypeAlias, Types,
};
use proc_macro2::{Ident, Span, TokenStream};
use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote, quote_spanned, ToTokens};
use syn::{parse_quote, Error, ItemMod, Result, Token};
use std::mem;
use syn::{parse_quote, Result, Token};
pub fn bridge(namespace: &Namespace, mut ffi: ItemMod) -> Result<TokenStream> {
pub fn bridge(namespace: &Namespace, mut ffi: Module) -> Result<TokenStream> {
let ref mut errors = Errors::new();
let content = ffi.content.take().ok_or(Error::new(
Span::call_site(),
"#[cxx::bridge] module must have inline contents",
))?;
let ref apis = syntax::parse_items(errors, content.1);
let content = mem::take(&mut ffi.content);
let ref apis = syntax::parse_items(errors, content);
let ref types = Types::collect(errors, apis);
errors.propagate()?;
check::typecheck(errors, namespace, apis, types);
@ -24,7 +23,7 @@ pub fn bridge(namespace: &Namespace, mut ffi: ItemMod) -> Result<TokenStream> {
Ok(expand(namespace, ffi, apis, types))
}
fn expand(namespace: &Namespace, ffi: ItemMod, apis: &[Api], types: &Types) -> TokenStream {
fn expand(namespace: &Namespace, ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
let mut expanded = TokenStream::new();
let mut hidden = TokenStream::new();

View File

@ -13,9 +13,10 @@ mod expand;
mod syntax;
mod type_id;
use crate::syntax::file::Module;
use crate::syntax::namespace::Namespace;
use proc_macro::TokenStream;
use syn::{parse_macro_input, ItemMod, LitStr};
use syn::{parse_macro_input, LitStr};
/// `#[cxx::bridge] mod ffi { ... }`
///
@ -39,7 +40,7 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
let _ = syntax::error::ERRORS;
let namespace = parse_macro_input!(args as Namespace);
let ffi = parse_macro_input!(input as ItemMod);
let ffi = parse_macro_input!(input as Module);
expand::bridge(&namespace, ffi)
.unwrap_or_else(|err| err.to_compile_error())

47
syntax/file.rs Normal file
View File

@ -0,0 +1,47 @@
use proc_macro2::Span;
use syn::parse::{Error, Parse, ParseStream, Result};
use syn::{braced, token, Attribute, Ident, Item, Token, Visibility};
pub struct Module {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
// TODO: unsafety
pub mod_token: Token![mod],
pub ident: Ident,
pub brace_token: token::Brace,
pub content: Vec<Item>,
}
impl Parse for Module {
fn parse(input: ParseStream) -> Result<Self> {
let mut attrs = input.call(Attribute::parse_outer)?;
let vis: Visibility = input.parse()?;
let mod_token: Token![mod] = input.parse()?;
let ident: Ident = input.parse()?;
if input.peek(Token![;]) {
return Err(Error::new(
Span::call_site(),
"#[cxx::bridge] module must have inline contents",
))?;
}
let content;
let brace_token = braced!(content in input);
attrs.extend(content.call(Attribute::parse_inner)?);
let mut items = Vec::new();
while !content.is_empty() {
items.push(content.parse()?);
}
Ok(Module {
attrs,
vis,
mod_token,
ident,
brace_token,
content: items,
})
}
}

View File

@ -7,6 +7,7 @@ mod derive;
mod discriminant;
mod doc;
pub mod error;
pub mod file;
pub mod ident;
mod impls;
pub mod mangle;