Skip to content

Commit

Permalink
Support deriving Component impl for specific app
Browse files Browse the repository at this point in the history
  • Loading branch information
jarrodldavis committed Mar 20, 2022
1 parent 840b980 commit 80db672
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 27 deletions.
6 changes: 3 additions & 3 deletions core/tests/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ mod example_app;

use self::example_app::{ExampleApp, ExampleConfig};
use abscissa_core::{
component, Application, Component, FrameworkError, FrameworkErrorKind::ComponentError, Shutdown,
component, Component, FrameworkError, FrameworkErrorKind::ComponentError, Shutdown,
};
use std::sync::atomic::{AtomicBool, Ordering};

Expand Down Expand Up @@ -33,14 +33,14 @@ impl FoobarComponent {

/// Example component #2
#[derive(Component, Debug, Default)]
#[component(after_config, before_shutdown)]
#[component(application = "ExampleApp", after_config, before_shutdown)]
pub struct BazComponent {
pub after_config_run: bool,
pub before_shutdown_run: AtomicBool,
}

impl BazComponent {
fn after_config<A: Application>(&mut self, _config: &A::Cfg) -> Result<(), FrameworkError> {
fn after_config(&mut self, _config: &ExampleConfig) -> Result<(), FrameworkError> {
self.after_config_run = true;
Ok(())
}
Expand Down
84 changes: 60 additions & 24 deletions derive/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,41 @@ pub fn derive_component(s: Structure<'_>) -> TokenStream {
let before_shutdown = attrs.before_shutdown();
let dependency_methods = attrs.dependency_methods();

s.gen_impl(quote! {
gen impl<A> Component<A> for @Self
where
A: #abscissa_core::Application
{
#[doc = "Identifier for this component"]
fn id(&self) -> #abscissa_core::component::Id {
// TODO(tarcieri): use `core::any::type_name` here when stable
#abscissa_core::component::Id::new(concat!(module_path!(), "::", stringify!(#name)))
}
let body = quote! {
#[doc = "Identifier for this component"]
fn id(&self) -> #abscissa_core::component::Id {
// TODO(tarcieri): use `core::any::type_name` here when stable
#abscissa_core::component::Id::new(concat!(module_path!(), "::", stringify!(#name)))
}

#[doc = "Version of this component"]
fn version(&self) -> #abscissa_core::Version {
#abscissa_core::Version::parse(env!("CARGO_PKG_VERSION")).unwrap()
}
#[doc = "Version of this component"]
fn version(&self) -> #abscissa_core::Version {
#abscissa_core::Version::parse(env!("CARGO_PKG_VERSION")).unwrap()
}

#dependency_methods

#dependency_methods
#after_config

#after_config
#before_shutdown
};

#before_shutdown
s.gen_impl(match attrs.application() {
Some(application) => {
quote! {
gen impl Component<#application> for @Self {
#body
}
}
}
None => quote! {
gen impl<A> Component<A> for @Self
where
A: #abscissa_core::Application
{
#body
}
},
})
}

Expand All @@ -44,6 +57,8 @@ pub fn derive_component(s: Structure<'_>) -> TokenStream {
struct ComponentAttributes {
after_config: bool,

application: Option<String>,

before_shutdown: bool,

/// Special attribute used by `abscissa_core` to `derive(Component)`.
Expand All @@ -60,6 +75,7 @@ impl ComponentAttributes {
/// Parse component attributes from custom derive input.
pub fn from_derive_input(input: &DeriveInput) -> Self {
let mut after_config = false;
let mut application = None;
let mut before_shutdown = false;
let mut core = false;
let mut inject = Vec::new();
Expand All @@ -79,6 +95,13 @@ impl ComponentAttributes {
Some(id) if id == "core" => core = true,
_ => panic!("malformed `component` attribute: {:?}", meta),
},
NestedMeta::Meta(Meta::NameValue(MetaNameValue {
path,
lit: Lit::Str(lit_str),
..
})) if path.is_ident("application") => {
application = Some(lit_str.value())
}
NestedMeta::Meta(Meta::NameValue { .. }) => {
inject.push(InjectAttribute::from_nested_meta(meta))
}
Expand All @@ -92,6 +115,7 @@ impl ComponentAttributes {

Self {
after_config,
application,
before_shutdown,
core,
inject,
Expand All @@ -109,17 +133,29 @@ impl ComponentAttributes {
}

pub fn after_config(&self) -> TokenStream {
if !self.after_config {
return quote!();
}
let abscissa_core = self.abscissa_core_crate();

quote! {
fn after_config(&mut self, config: &A::Cfg) -> Result<(), FrameworkError> {
self.after_config::<A>(config)
}
match (self.after_config, self.application()) {
(false, _) => quote!(),
(true, None) => quote! {
fn after_config(&mut self, config: &A::Cfg) -> Result<(), FrameworkError> {
self.after_config::<A>(config)
}
},
(true, Some(application)) => quote! {
fn after_config(&mut self, config: &<#application as #abscissa_core::Application>::Cfg) -> Result<(), FrameworkError> {
self.after_config(config)
}
},
}
}

pub fn application(&self) -> Option<Ident> {
self.application
.as_ref()
.map(|application| Ident::new(application.as_ref(), Span::call_site()))
}

pub fn before_shutdown(&self) -> TokenStream {
if !self.before_shutdown {
return quote!();
Expand Down

0 comments on commit 80db672

Please sign in to comment.