Skip to content

Update inventory requirement from 0.1.10 to 0.2.0 #158

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Nov 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ structopt = "0.3.25"

# "macros" feature dependencies
cucumber-codegen = { version = "0.11.0-dev", path = "./codegen", optional = true }
inventory = { version = "0.1.10", optional = true }
inventory = { version = "0.2", optional = true }

# "output-json" feature dependencies
serde = { version = "1.0.103", features = ["derive"], optional = true }
Expand Down
65 changes: 44 additions & 21 deletions codegen/src/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

use std::mem;

use inflections::case::to_pascal_case;
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use regex::{self, Regex};
Expand Down Expand Up @@ -101,7 +102,7 @@ impl Step {
let func_name = &func.sig.ident;

let world = parse_world_from_args(&self.func.sig)?;
let constructor_method = self.constructor_method();
let step_type = self.step_type();
let (func_args, addon_parsing) =
self.fn_arguments_and_additional_parsing()?;

Expand Down Expand Up @@ -129,30 +130,52 @@ impl Step {
::std::boxed::Box::pin(f)
}

#caller_name
let f: ::cucumber::Step<#world> = #caller_name;
f
}
};

Ok(quote! {
#func

#[automatically_derived]
::cucumber::codegen::submit!(
#![crate = ::cucumber::codegen] {
<#world as ::cucumber::codegen::WorldInventory<
_, _, _,
>>::#constructor_method(
::cucumber::step::Location {
path: ::std::convert::From::from(::std::file!()),
line: ::std::line!(),
column: ::std::column!(),
},
::cucumber::codegen::Regex::new(#step_matcher)
.unwrap(),
#step_caller,
)
::cucumber::codegen::submit!({
// TODO: Remove this, once `#![feature(more_qualified_paths)]`
// is stabilized:
// https://github.com/rust-lang/rust/issues/86935
type StepAlias =
<#world as ::cucumber::codegen::WorldInventory>::#step_type;

StepAlias {
loc: ::cucumber::step::Location {
path: ::std::file!(),
line: ::std::line!(),
column: ::std::column!(),
},
regex: {
// This hack exists, as `fn item` to `fn pointer`
// coercion can be done inside `const`, but not
// `const fn`.
let lazy: ::cucumber::codegen::LazyRegex = || {
static LAZY: ::cucumber::codegen::Lazy<
::cucumber::codegen::Regex
> = ::cucumber::codegen::Lazy::new(|| {
::cucumber::codegen::Regex::new(#step_matcher)
.unwrap()
});
LAZY.clone()
};
lazy
},
func: {
// This hack exists, as `fn item` to `fn pointer`
// coercion can be done inside `const`, but not
// `const fn`.
const F: ::cucumber::Step<#world> = #step_caller;
F
},
}
);
});
})
}

Expand Down Expand Up @@ -238,10 +261,10 @@ impl Step {
}
}

/// Composes a name of the `cucumber::codegen::WorldInventory` method to
/// wire this [`Step`] with.
fn constructor_method(&self) -> syn::Ident {
format_ident!("new_{}", self.attr_name)
/// Composes a name of the `cucumber::codegen::WorldInventory` associated
/// type to wire this [`Step`] with.
fn step_type(&self) -> syn::Ident {
format_ident!("{}", to_pascal_case(self.attr_name))
}

/// Returns [`syn::Ident`] and parsing code of the given function's
Expand Down
135 changes: 47 additions & 88 deletions codegen/src/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use proc_macro2::TokenStream;
use quote::{format_ident, quote};

/// Generates code of `#[derive(WorldInit)]` macro expansion.
#[allow(clippy::similar_names)]
pub(crate) fn world_init(
input: TokenStream,
steps: &[&str],
Expand All @@ -26,10 +27,16 @@ pub(crate) fn world_init(
let step_types = step_types(steps, world);
let step_structs = generate_step_structs(steps, &input);

let given_ty = &step_types[0];
let when_ty = &step_types[1];
let then_ty = &step_types[2];

Ok(quote! {
impl ::cucumber::codegen::WorldInventory<
#( #step_types, )*
> for #world {}
impl ::cucumber::codegen::WorldInventory for #world {
type Given = #given_ty;
type When = #when_ty;
type Then = #then_ty;
}

#( #step_structs )*
})
Expand All @@ -41,10 +48,7 @@ pub(crate) fn world_init(
fn step_types(steps: &[&str], world: &syn::Ident) -> Vec<syn::Ident> {
steps
.iter()
.map(|step| {
let step = to_pascal_case(step);
format_ident!("Cucumber{}{}", step, world)
})
.map(|step| format_ident!("Cucumber{}{}", to_pascal_case(step), world))
.collect()
}

Expand All @@ -53,7 +57,8 @@ fn generate_step_structs(
steps: &[&str],
world: &syn::DeriveInput,
) -> Vec<TokenStream> {
let (world, world_vis) = (&world.ident, &world.vis);
let world_vis = &world.vis;
let world = &world.ident;

step_types(steps, world)
.iter()
Expand All @@ -63,35 +68,23 @@ fn generate_step_structs(
#[doc(hidden)]
#world_vis struct #ty {
#[doc(hidden)]
pub loc: ::cucumber::step::Location,
#world_vis loc: ::cucumber::step::Location,

#[doc(hidden)]
pub regex: ::cucumber::codegen::Regex,
#world_vis regex: ::cucumber::codegen::LazyRegex,

#[doc(hidden)]
pub func: ::cucumber::Step<#world>,
#world_vis func: ::cucumber::Step<#world>,
}

#[automatically_derived]
impl ::cucumber::codegen::StepConstructor<#world> for #ty {
fn new (
loc: ::cucumber::step::Location,
regex: ::cucumber::codegen::Regex,
func: ::cucumber::Step<#world>,
) -> Self {
Self { loc, regex, func }
}

fn inner(&self) -> (
::cucumber::step::Location,
::cucumber::codegen::Regex,
::cucumber::codegen::LazyRegex,
::cucumber::Step<#world>,
) {
(
self.loc.clone(),
self.regex.clone(),
self.func.clone(),
)
(self.loc, self.regex, self.func)
}
}

Expand All @@ -114,45 +107,35 @@ mod spec {
};

let output = quote! {
impl ::cucumber::codegen::WorldInventory<
CucumberGivenWorld, CucumberWhenWorld, CucumberThenWorld,
> for World {}
impl ::cucumber::codegen::WorldInventory for World {
type Given = CucumberGivenWorld;
type When = CucumberWhenWorld;
type Then = CucumberThenWorld;
}

#[automatically_derived]
#[doc(hidden)]
pub struct CucumberGivenWorld {
#[doc(hidden)]
pub loc: ::cucumber::step::Location,
#[doc(hidden)]
pub loc: ::cucumber::step::Location,

#[doc(hidden)]
pub regex: ::cucumber::codegen::Regex,
#[doc(hidden)]
pub regex: ::cucumber::codegen::LazyRegex,

#[doc(hidden)]
pub func: ::cucumber::Step<World>,
#[doc(hidden)]
pub func: ::cucumber::Step<World>,
}

#[automatically_derived]
impl ::cucumber::codegen::StepConstructor<World> for
CucumberGivenWorld
{
fn new (
loc: ::cucumber::step::Location,
regex: ::cucumber::codegen::Regex,
func: ::cucumber::Step<World>,
) -> Self {
Self { loc, regex, func }
}

fn inner(&self) -> (
::cucumber::step::Location,
::cucumber::codegen::Regex,
::cucumber::codegen::LazyRegex,
::cucumber::Step<World>,
) {
(
self.loc.clone(),
self.regex.clone(),
self.func.clone(),
)
(self.loc, self.regex, self.func)
}
}

Expand All @@ -162,38 +145,26 @@ mod spec {
#[automatically_derived]
#[doc(hidden)]
pub struct CucumberWhenWorld {
#[doc(hidden)]
pub loc: ::cucumber::step::Location,
#[doc(hidden)]
pub loc: ::cucumber::step::Location,

#[doc(hidden)]
pub regex: ::cucumber::codegen::Regex,
#[doc(hidden)]
pub regex: ::cucumber::codegen::LazyRegex,

#[doc(hidden)]
pub func: ::cucumber::Step<World>,
#[doc(hidden)]
pub func: ::cucumber::Step<World>,
}

#[automatically_derived]
impl ::cucumber::codegen::StepConstructor<World> for
CucumberWhenWorld
{
fn new (
loc: ::cucumber::step::Location,
regex: ::cucumber::codegen::Regex,
func: ::cucumber::Step<World>,
) -> Self {
Self { loc, regex, func }
}

fn inner(&self) -> (
::cucumber::step::Location,
::cucumber::codegen::Regex,
::cucumber::codegen::LazyRegex,
::cucumber::Step<World>,
) {
(
self.loc.clone(),
self.regex.clone(),
self.func.clone(),
)
(self.loc, self.regex, self.func)
}
}

Expand All @@ -203,38 +174,26 @@ mod spec {
#[automatically_derived]
#[doc(hidden)]
pub struct CucumberThenWorld {
#[doc(hidden)]
pub loc: ::cucumber::step::Location,
#[doc(hidden)]
pub loc: ::cucumber::step::Location,

#[doc(hidden)]
pub regex: ::cucumber::codegen::Regex,
#[doc(hidden)]
pub regex: ::cucumber::codegen::LazyRegex,

#[doc(hidden)]
pub func: ::cucumber::Step<World>,
#[doc(hidden)]
pub func: ::cucumber::Step<World>,
}

#[automatically_derived]
impl ::cucumber::codegen::StepConstructor<World> for
CucumberThenWorld
{
fn new (
loc: ::cucumber::step::Location,
regex: ::cucumber::codegen::Regex,
func: ::cucumber::Step<World>,
) -> Self {
Self { loc, regex, func }
}

fn inner(&self) -> (
::cucumber::step::Location,
::cucumber::codegen::Regex,
::cucumber::codegen::LazyRegex,
::cucumber::Step<World>,
) {
(
self.loc.clone(),
self.regex.clone(),
self.func.clone(),
)
(self.loc, self.regex, self.func)
}
}

Expand Down
11 changes: 3 additions & 8 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ and may be extended with custom CLI options additionally.
# }
# }
#
# let fut = async {
# #[tokio::main(flavor = "current_thread")]
# async fn main() {
#[derive(StructOpt)]
struct CustomOpts {
/// Additional time to wait in before hook.
Expand All @@ -83,13 +84,7 @@ MyWorld::cucumber()
.with_cli(opts)
.run_and_exit("tests/features/readme")
.await;
# };
#
# tokio::runtime::Builder::new_current_thread()
# .enable_all()
# .build()
# .unwrap()
# .block_on(fut);
# }
```

[`Cucumber`]: crate::Cucumber
Expand Down
Loading