lib.rs 3.61 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Copyright 2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.

#![deny(unused_crate_dependencies)]

Shawn Tabrizi's avatar
Shawn Tabrizi committed
19
use proc_macro2::{Ident, Span, TokenStream};
20
use quote::{quote, ToTokens};
Shawn Tabrizi's avatar
Shawn Tabrizi committed
21
use syn::{parse2, Result};
22
23

mod impl_builder;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
24
25
26
mod impl_channels_out;
mod impl_dispatch;
mod impl_message_wrapper;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
mod impl_misc;
mod impl_overseer;
mod parse_attr;
mod parse_struct;

use impl_builder::*;
use impl_channels_out::*;
use impl_dispatch::*;
use impl_message_wrapper::*;
use impl_misc::*;
use impl_overseer::*;
use parse_attr::*;
use parse_struct::*;

#[cfg(test)]
mod tests;

#[proc_macro_attribute]
Shawn Tabrizi's avatar
Shawn Tabrizi committed
45
46
47
48
pub fn overlord(
	attr: proc_macro::TokenStream,
	item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
49
50
	let attr: TokenStream = attr.into();
	let item: TokenStream = item.into();
Shawn Tabrizi's avatar
Shawn Tabrizi committed
51
52
53
	impl_overseer_gen(attr, item)
		.unwrap_or_else(|err| err.to_compile_error())
		.into()
54
55
}

Shawn Tabrizi's avatar
Shawn Tabrizi committed
56
57
58
59
pub(crate) fn impl_overseer_gen(
	attr: TokenStream,
	orig: TokenStream,
) -> Result<proc_macro2::TokenStream> {
60
61
62
63
64
65
	let args: AttrArgs = parse2(attr)?;
	let message_wrapper = args.message_wrapper;

	let of: OverseerGuts = parse2(orig)?;

	let support_crate_name = if cfg!(test) {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
66
		quote! {crate}
67
68
69
70
71
	} else {
		use proc_macro_crate::{crate_name, FoundCrate};
		let crate_name = crate_name("polkadot-overseer-gen")
			.expect("Support crate polkadot-overseer-gen is present in `Cargo.toml`. qed");
		match crate_name {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
72
73
74
			FoundCrate::Itself => quote! {crate},
			FoundCrate::Name(name) => Ident::new(&name, Span::call_site()).to_token_stream(),
		}
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
	};
	let info = OverseerInfo {
		support_crate_name,
		subsystems: of.subsystems,
		baggage: of.baggage,
		overseer_name: of.name,
		message_wrapper,
		message_channel_capacity: args.message_channel_capacity,
		signal_channel_capacity: args.signal_channel_capacity,
		extern_event_ty: args.extern_event_ty,
		extern_signal_ty: args.extern_signal_ty,
		extern_error_ty: args.extern_error_ty,
		extern_network_ty: args.extern_network_ty,
		outgoing_ty: args.outgoing_ty,
	};

	let mut additive = impl_overseer_struct(&info);
	additive.extend(impl_builder(&info));

	additive.extend(impl_overseen_subsystem(&info));
	additive.extend(impl_channels_out_struct(&info));
	additive.extend(impl_misc(&info));

	additive.extend(impl_message_wrapper_enum(&info)?);
	additive.extend(impl_dispatch(&info));

101
	if cfg!(feature = "expansion") {
102
103
		use std::io::Write;

104
105
106
		let out = env!("OUT_DIR");
		let out = std::path::PathBuf::from(out);
		let path = out.join("overlord-expansion.rs");
107
108
109
110
111
112
113
114
115
116
117
118
119
		let mut f = std::fs::OpenOptions::new()
			.write(true)
			.create(true)
			.truncate(true)
			.open(&path)
			.expect("File exists. qed");
		f.write_all(
			&mut format!("// {:?} \n{}", std::time::SystemTime::now(), additive).as_bytes(),
		)
		.expect("Got permissions to write to file. qed");
		std::process::Command::new("rustfmt")
			.arg("--edition=2018")
			.arg(&path)
120
			.current_dir(out)
121
122
			.spawn()
			.expect("Running rustfmt works. qed");
123
124
125
126
127
128
129

		let path = path.display().to_string();
		Ok(quote! {
			include!( #path );
		})
	} else {
		Ok(additive)
130
	}
131
}