Skip to content

Commit 3c64a4e

Browse files
committed
Parse full file using the new Module parser
1 parent 17c3230 commit 3c64a4e

File tree

7 files changed

+84
-77
lines changed

7 files changed

+84
-77
lines changed

gen/src/error.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
1616
#[derive(Debug)]
1717
pub(super) enum Error {
1818
NoBridgeMod,
19-
OutOfLineMod,
2019
Io(io::Error),
2120
Syn(syn::Error),
2221
}
@@ -25,7 +24,6 @@ impl Display for Error {
2524
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2625
match self {
2726
Error::NoBridgeMod => write!(f, "no #[cxx::bridge] module found"),
28-
Error::OutOfLineMod => write!(f, "#[cxx::bridge] module must have inline contents"),
2927
Error::Io(err) => err.fmt(f),
3028
Error::Syn(err) => err.fmt(f),
3129
}

gen/src/file.rs

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,71 @@
1-
use syn::parse::{Parse, ParseStream, Result};
2-
use syn::{Attribute, Item};
1+
use crate::syntax::file::Module;
2+
use crate::syntax::namespace::Namespace;
3+
use syn::parse::discouraged::Speculative;
4+
use syn::parse::{Error, Parse, ParseStream, Result};
5+
use syn::{braced, Attribute, Ident, Item, Token, Visibility};
36

47
pub struct File {
5-
pub attrs: Vec<Attribute>,
6-
pub items: Vec<Item>,
8+
pub modules: Vec<Module>,
79
}
810

911
impl Parse for File {
1012
fn parse(input: ParseStream) -> Result<Self> {
11-
let attrs = input.call(Attribute::parse_inner)?;
13+
let mut modules = Vec::new();
14+
input.call(Attribute::parse_inner)?;
15+
parse(input, &mut modules)?;
16+
Ok(File { modules })
17+
}
18+
}
19+
20+
fn parse(input: ParseStream, modules: &mut Vec<Module>) -> Result<()> {
21+
while !input.is_empty() {
22+
let mut cxx_bridge = false;
23+
let mut namespace = Namespace::none();
24+
let attrs = input.call(Attribute::parse_outer)?;
25+
for attr in &attrs {
26+
let path = &attr.path.segments;
27+
if path.len() == 2 && path[0].ident == "cxx" && path[1].ident == "bridge" {
28+
cxx_bridge = true;
29+
namespace = parse_args(attr)?;
30+
break;
31+
}
32+
}
1233

13-
let mut items = Vec::new();
14-
while !input.is_empty() {
15-
items.push(input.parse()?);
34+
let ahead = input.fork();
35+
ahead.parse::<Visibility>()?;
36+
ahead.parse::<Option<Token![unsafe]>>()?;
37+
if !ahead.peek(Token![mod]) {
38+
let item: Item = input.parse()?;
39+
if cxx_bridge {
40+
return Err(Error::new_spanned(item, "expected a module"));
41+
}
42+
continue;
1643
}
1744

18-
Ok(File { attrs, items })
45+
if cxx_bridge {
46+
let mut module: Module = input.parse()?;
47+
module.namespace = namespace;
48+
module.attrs = attrs;
49+
modules.push(module);
50+
} else {
51+
input.advance_to(&ahead);
52+
input.parse::<Token![mod]>()?;
53+
input.parse::<Ident>()?;
54+
let semi: Option<Token![;]> = input.parse()?;
55+
if semi.is_none() {
56+
let content;
57+
braced!(content in input);
58+
parse(&content, modules)?;
59+
}
60+
}
61+
}
62+
Ok(())
63+
}
64+
65+
fn parse_args(attr: &Attribute) -> Result<Namespace> {
66+
if attr.tokens.is_empty() {
67+
Ok(Namespace::none())
68+
} else {
69+
attr.parse_args()
1970
}
2071
}

gen/src/find.rs

Lines changed: 0 additions & 47 deletions
This file was deleted.

gen/src/mod.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
mod error;
55
mod file;
6-
mod find;
76
pub(super) mod include;
87
pub(super) mod out;
98
mod write;
@@ -13,17 +12,10 @@ mod tests;
1312

1413
use self::error::{format_err, Error, Result};
1514
use self::file::File;
16-
use crate::syntax::namespace::Namespace;
1715
use crate::syntax::report::Errors;
1816
use crate::syntax::{self, check, Types};
1917
use std::fs;
2018
use std::path::Path;
21-
use syn::Item;
22-
23-
struct Input {
24-
namespace: Namespace,
25-
module: Vec<Item>,
26-
}
2719

2820
#[derive(Default)]
2921
pub(super) struct Opt {
@@ -64,9 +56,13 @@ fn generate(source: &str, opt: Opt, header: bool) -> Result<Vec<u8>> {
6456
proc_macro2::fallback::force();
6557
let ref mut errors = Errors::new();
6658
let syntax: File = syn::parse_str(source)?;
67-
let bridge = find::find_bridge_mod(syntax)?;
59+
let bridge = syntax
60+
.modules
61+
.into_iter()
62+
.next()
63+
.ok_or(Error::NoBridgeMod)?;
6864
let ref namespace = bridge.namespace;
69-
let ref apis = syntax::parse_items(errors, bridge.module);
65+
let ref apis = syntax::parse_items(errors, bridge.content);
7066
let ref types = Types::collect(errors, apis);
7167
errors.propagate()?;
7268
check::typecheck(errors, namespace, apis, types);

macro/src/expand.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,23 @@ use quote::{format_ident, quote, quote_spanned, ToTokens};
1111
use std::mem;
1212
use syn::{parse_quote, Result, Token};
1313

14-
pub fn bridge(namespace: &Namespace, mut ffi: Module) -> Result<TokenStream> {
14+
pub fn bridge(mut ffi: Module) -> Result<TokenStream> {
1515
let ref mut errors = Errors::new();
1616
let content = mem::take(&mut ffi.content);
1717
let ref apis = syntax::parse_items(errors, content);
1818
let ref types = Types::collect(errors, apis);
1919
errors.propagate()?;
20+
let namespace = &ffi.namespace;
2021
check::typecheck(errors, namespace, apis, types);
2122
errors.propagate()?;
2223

23-
Ok(expand(namespace, ffi, apis, types))
24+
Ok(expand(ffi, apis, types))
2425
}
2526

26-
fn expand(namespace: &Namespace, ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
27+
fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
2728
let mut expanded = TokenStream::new();
2829
let mut hidden = TokenStream::new();
30+
let namespace = &ffi.namespace;
2931

3032
for api in apis {
3133
if let Api::RustType(ety) = api {

macro/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
4040
let _ = syntax::error::ERRORS;
4141

4242
let namespace = parse_macro_input!(args as Namespace);
43-
let ffi = parse_macro_input!(input as Module);
43+
let mut ffi = parse_macro_input!(input as Module);
44+
ffi.namespace = namespace;
4445

45-
expand::bridge(&namespace, ffi)
46+
expand::bridge(ffi)
4647
.unwrap_or_else(|err| err.to_compile_error())
4748
.into()
4849
}

syntax/file.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
use proc_macro2::Span;
1+
use crate::syntax::namespace::Namespace;
2+
use quote::quote;
23
use syn::parse::{Error, Parse, ParseStream, Result};
34
use syn::{braced, token, Attribute, Ident, Item, Token, Visibility};
45

56
pub struct Module {
7+
pub namespace: Namespace,
68
pub attrs: Vec<Attribute>,
79
pub vis: Visibility,
810
// TODO: unsafety
@@ -14,14 +16,17 @@ pub struct Module {
1416

1517
impl Parse for Module {
1618
fn parse(input: ParseStream) -> Result<Self> {
19+
let namespace = Namespace::none();
1720
let mut attrs = input.call(Attribute::parse_outer)?;
1821
let vis: Visibility = input.parse()?;
1922
let mod_token: Token![mod] = input.parse()?;
2023
let ident: Ident = input.parse()?;
2124

22-
if input.peek(Token![;]) {
23-
return Err(Error::new(
24-
Span::call_site(),
25+
let semi: Option<Token![;]> = input.parse()?;
26+
if let Some(semi) = semi {
27+
let span = quote!(#vis #mod_token #semi);
28+
return Err(Error::new_spanned(
29+
span,
2530
"#[cxx::bridge] module must have inline contents",
2631
))?;
2732
}
@@ -36,6 +41,7 @@ impl Parse for Module {
3641
}
3742

3843
Ok(Module {
44+
namespace,
3945
attrs,
4046
vis,
4147
mod_token,

0 commit comments

Comments
 (0)