Skip to content

Commit

Permalink
Add UI test for missing argument in args_into (#145)
Browse files Browse the repository at this point in the history
This commit introduces a compile error when using missing argument in `args_into`.

Here's an example:
```rust
#[swift_bridge::bridge]
mod ffi {
    extern "Rust" {
        #[swift_bridge(args_into = (arg, arg_typo))]
        fn some_function(arg: u8);
    }
}
```

```
error: arg_typo: Unknown argument
       Could not find "arg_typo" in "fn some_function(arg : u8)".
 --> tests/ui/args-into-argument-not-found.rs:7:42
  |
7 |         #[swift_bridge(args_into = (arg, arg_typo))]
  |                                          ^^^^^^^^

```
  • Loading branch information
NiwakaDev authored Jan 25, 2023
1 parent d064b25 commit 3cd5ab1
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 3 deletions.
14 changes: 13 additions & 1 deletion crates/swift-bridge-ir/src/errors/parse_error.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
use proc_macro2::Ident;
use quote::ToTokens;
use syn::{Error, FnArg, Item, Receiver};
use syn::{ForeignItemType, LitStr};
use syn::{ForeignItemFn, ForeignItemType, LitStr};
use syn::{Token, Type};

// <!-- ANCHOR: mdbook-parse-error-enum -->
pub(crate) enum ParseError {
ArgsIntoArgNotFound {
func: ForeignItemFn,
missing_arg: Ident,
},
/// `extern {}`
AbiNameMissing {
/// `extern {}`
Expand Down Expand Up @@ -71,6 +75,14 @@ pub(crate) enum IdentifiableParseError {
impl Into<syn::Error> for ParseError {
fn into(self) -> Error {
match self {
ParseError::ArgsIntoArgNotFound { func, missing_arg } => Error::new_spanned(
missing_arg.clone(),
format!(
r#"Argument "{}" was not found in the "fn {}(..)""#,
missing_arg,
func.sig.ident.to_token_stream().to_string()
),
),
ParseError::AbiNameMissing {
extern_token: extern_ident,
} => Error::new_spanned(
Expand Down
53 changes: 51 additions & 2 deletions crates/swift-bridge-ir/src/parse/parse_extern_mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::parsed_extern_fn::fn_arg_is_mutable_reference;
use crate::ParsedExternFn;
use quote::ToTokens;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use std::ops::Deref;
use syn::{FnArg, ForeignItem, ForeignItemFn, GenericParam, ItemForeignMod, Pat, ReturnType, Type};

Expand Down Expand Up @@ -160,7 +160,6 @@ impl<'a> ForeignModParser<'a> {
));
}
}

for arg in func.sig.inputs.iter() {
let is_mutable_ref = fn_arg_is_mutable_reference(arg);

Expand All @@ -180,7 +179,29 @@ impl<'a> ForeignModParser<'a> {
.push(ParseError::ArgCopyAndRefMut { arg: arg.clone() });
}
}
if let Some(ref args) = attributes.args_into {
let mut func_sig_args = HashSet::with_capacity(args.len());
for fn_arg in func.sig.inputs.iter() {
match fn_arg {
FnArg::Receiver(_) => {}
FnArg::Typed(pat_ty) => {
let fn_arg_name = pat_ty.pat.to_token_stream().to_string();
func_sig_args.insert(fn_arg_name);
}
}
}

for arg in args.iter() {
let arg_name = arg.to_token_stream().to_string();

if !func_sig_args.contains(&arg_name) {
self.errors.push(ParseError::ArgsIntoArgNotFound {
func: func.clone(),
missing_arg: arg.clone(),
})
}
}
}
let func = ParsedExternFn {
func,
associated_type,
Expand Down Expand Up @@ -866,6 +887,34 @@ mod tests {
);
}

/// Verify that we push errors for unknown arguments in a function
#[test]
fn error_args_into_arg_not_found_in_function() {
let tokens = quote! {
#[swift_bridge::bridge]
mod ffi {
extern "Rust" {
#[swift_bridge(args_into = (foo, bar))]
fn some_function(foo: u8);
}
}
};

let errors = parse_errors(tokens);

// Only "bar" should be missing argument.
assert_eq!(errors.len(), 1);
match &errors[0] {
ParseError::ArgsIntoArgNotFound {
func: _,
missing_arg,
} => {
assert_eq!(missing_arg, "bar")
}
_ => panic!(),
}
}

/// Verify that we push errors for function arguments that are both mutable and opaque Copy.
#[test]
fn error_if_mutable_opaque_copy_type() {
Expand Down
32 changes: 32 additions & 0 deletions crates/swift-bridge-macro/tests/ui/args-into-argument-not-found.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//! # To Run
//! cargo test -p swift-bridge-macro -- ui trybuild=args-into-argument-not-found.rs
#[swift_bridge::bridge]
mod ffi {
extern "Rust" {
#[swift_bridge(args_into = (arg, arg_typo))]
fn some_function(arg: u8);
}
extern "Rust" {
type SomeType;

#[swift_bridge(args_into = (foo, bar))]
fn some_method(&self, foo: u8);
}
}

fn some_function(arg: u8){

}

struct SomeType;

impl SomeType {
fn some_method(&self, foo: u8){

}
}

fn main() {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error: Argument "arg_typo" was not found in the "fn some_function(..)"
--> tests/ui/args-into-argument-not-found.rs:7:42
|
7 | #[swift_bridge(args_into = (arg, arg_typo))]
| ^^^^^^^^

error: Argument "bar" was not found in the "fn some_method(..)"
--> tests/ui/args-into-argument-not-found.rs:13:42
|
13 | #[swift_bridge(args_into = (foo, bar))]
| ^^^

0 comments on commit 3cd5ab1

Please sign in to comment.