refactor(derive-ahk): enforce no_implicit_prelude

Starting to implement the feedback I got from this post on Reddit
https://old.reddit.com/r/rust/comments/pa2997/code_review_request_first_derive_macro/.
This commit is contained in:
LGUG2Z
2021-08-23 11:08:26 -07:00
parent b61b03b1c9
commit fb4fe4d9c3
2 changed files with 64 additions and 34 deletions

View File

@@ -1,19 +1,28 @@
#![warn(clippy::all, clippy::nursery, clippy::pedantic)] #![warn(clippy::all, clippy::nursery, clippy::pedantic)]
#![allow(clippy::missing_errors_doc)] #![allow(clippy::missing_errors_doc)]
#![no_implicit_prelude]
use std::stringify; use ::std::clone::Clone;
use ::std::convert::From;
use ::std::convert::Into;
use ::std::iter::Extend;
use ::std::iter::Iterator;
use ::std::matches;
use ::std::string::ToString;
use ::std::unreachable;
use quote::quote; use ::quote::quote;
use syn::parse_macro_input; use ::std::option::Option::Some;
use syn::Data; use ::syn::parse_macro_input;
use syn::DataEnum; use ::syn::Data;
use syn::DeriveInput; use ::syn::DataEnum;
use syn::Fields; use ::syn::DeriveInput;
use syn::FieldsNamed; use ::syn::Fields;
use syn::FieldsUnnamed; use ::syn::FieldsNamed;
use ::syn::FieldsUnnamed;
#[proc_macro_derive(Ahk)] #[proc_macro_derive(AhkFunction)]
pub fn ahk(input: proc_macro::TokenStream) -> proc_macro::TokenStream { pub fn ahk_function(input: ::proc_macro::TokenStream) -> ::proc_macro::TokenStream {
let input = parse_macro_input!(input as DeriveInput); let input = parse_macro_input!(input as DeriveInput);
let name = input.ident; let name = input.ident;
@@ -21,22 +30,23 @@ pub fn ahk(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
Data::Struct(s) => match s.fields { Data::Struct(s) => match s.fields {
Fields::Named(FieldsNamed { named, .. }) => { Fields::Named(FieldsNamed { named, .. }) => {
let idents = named.iter().map(|f| &f.ident); let idents = named.iter().map(|f| &f.ident);
let arguments = format!("{}", quote! {#(#idents), *}); let arguments = quote! {#(#idents), *}.to_string();
let idents = named.iter().map(|f| &f.ident); let idents = named.iter().map(|f| &f.ident);
let called_arguments = format!("{}", quote! {#(%#idents%) *}) let called_arguments = quote! {#(%#idents%) *}
.to_string()
.replace(" %", "%") .replace(" %", "%")
.replace("% ", "%") .replace("% ", "%")
.replace("%%", "% %"); .replace("%%", "% %");
quote! { quote! {
impl #name { impl AhkFunction for #name {
fn ahk_function() -> String { fn generate_ahk_function() -> String {
format!(r#" ::std::format!(r#"
{}({}) {{ {}({}) {{
Run, komorebic.exe {} {}, , Hide Run, komorebic.exe {} {}, , Hide
}}"#, }}"#,
stringify!(#name), ::std::stringify!(#name),
#arguments, #arguments,
stringify!(#name).to_kebab_case(), stringify!(#name).to_kebab_case(),
#called_arguments #called_arguments
@@ -47,31 +57,42 @@ pub fn ahk(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
} }
_ => unreachable!("only to be used on structs with named fields"), _ => unreachable!("only to be used on structs with named fields"),
}, },
_ => unreachable!("only to be used on structs"),
}
.into()
}
#[proc_macro_derive(AhkLibrary)]
pub fn ahk_library(input: ::proc_macro::TokenStream) -> ::proc_macro::TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = input.ident;
match input.data {
Data::Enum(DataEnum { variants, .. }) => { Data::Enum(DataEnum { variants, .. }) => {
let enums = variants.iter().filter(|&v| { let enums = variants.iter().filter(|&v| {
matches!(v.fields, Fields::Unit) || matches!(v.fields, Fields::Unnamed(..)) matches!(v.fields, Fields::Unit) || matches!(v.fields, Fields::Unnamed(..))
}); });
let mut stream = proc_macro2::TokenStream::new(); let mut stream = ::proc_macro2::TokenStream::new();
for variant in enums.clone() { for variant in enums.clone() {
match &variant.fields { match &variant.fields {
Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => { Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => {
for field in unnamed { for field in unnamed {
stream.extend(quote! { stream.extend(quote! {
v.push(#field::ahk_function()); v.push(#field::generate_ahk_function());
}); });
} }
} }
Fields::Unit => { Fields::Unit => {
let name = &variant.ident; let name = &variant.ident;
stream.extend(quote! { stream.extend(quote! {
v.push(format!(r#" v.push(::std::format!(r#"
{}() {{ {}() {{
Run, komorebic.exe {}, , Hide Run, komorebic.exe {}, , Hide
}}"#, }}"#,
stringify!(#name), ::std::stringify!(#name),
stringify!(#name).to_kebab_case() ::std::stringify!(#name).to_kebab_case()
)); ));
}); });
} }
@@ -93,7 +114,7 @@ pub fn ahk(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
} }
} }
} }
Data::Union(_) => unreachable!("only to be used on enums and structs"), _ => unreachable!("only to be used on enums"),
} }
.into() .into()
} }

View File

@@ -26,7 +26,8 @@ use bindings::Windows::Win32::Foundation::HWND;
use bindings::Windows::Win32::UI::WindowsAndMessaging::ShowWindow; use bindings::Windows::Win32::UI::WindowsAndMessaging::ShowWindow;
use bindings::Windows::Win32::UI::WindowsAndMessaging::SHOW_WINDOW_CMD; use bindings::Windows::Win32::UI::WindowsAndMessaging::SHOW_WINDOW_CMD;
use bindings::Windows::Win32::UI::WindowsAndMessaging::SW_RESTORE; use bindings::Windows::Win32::UI::WindowsAndMessaging::SW_RESTORE;
use derive_ahk::Ahk; use derive_ahk::AhkFunction;
use derive_ahk::AhkLibrary;
use komorebi_core::ApplicationIdentifier; use komorebi_core::ApplicationIdentifier;
use komorebi_core::CycleDirection; use komorebi_core::CycleDirection;
use komorebi_core::Flip; use komorebi_core::Flip;
@@ -35,6 +36,14 @@ use komorebi_core::OperationDirection;
use komorebi_core::Sizing; use komorebi_core::Sizing;
use komorebi_core::SocketMessage; use komorebi_core::SocketMessage;
trait AhkLibrary {
fn generate_ahk_library() -> String;
}
trait AhkFunction {
fn generate_ahk_function() -> String;
}
#[derive(ArgEnum)] #[derive(ArgEnum)]
enum BooleanState { enum BooleanState {
Enable, Enable,
@@ -55,7 +64,7 @@ macro_rules! gen_enum_subcommand_args {
( $( $name:ident: $element:ty ),+ ) => { ( $( $name:ident: $element:ty ),+ ) => {
$( $(
paste! { paste! {
#[derive(clap::Clap, derive_ahk::Ahk)] #[derive(clap::Clap, derive_ahk::AhkFunction)]
pub struct $name { pub struct $name {
#[clap(arg_enum)] #[clap(arg_enum)]
[<$element:snake>]: $element [<$element:snake>]: $element
@@ -80,7 +89,7 @@ macro_rules! gen_target_subcommand_args {
// SubCommand Pattern // SubCommand Pattern
( $( $name:ident ),+ ) => { ( $( $name:ident ),+ ) => {
$( $(
#[derive(clap::Clap, derive_ahk::Ahk)] #[derive(clap::Clap, derive_ahk::AhkFunction)]
pub struct $name { pub struct $name {
/// Target index (zero-indexed) /// Target index (zero-indexed)
target: usize, target: usize,
@@ -104,7 +113,7 @@ macro_rules! gen_workspace_subcommand_args {
( $( $name:ident: $(#[enum] $(@$arg_enum:tt)?)? $value:ty ),+ ) => ( ( $( $name:ident: $(#[enum] $(@$arg_enum:tt)?)? $value:ty ),+ ) => (
paste! { paste! {
$( $(
#[derive(clap::Clap, derive_ahk::Ahk)] #[derive(clap::Clap, derive_ahk::AhkFunction)]
pub struct [<Workspace $name>] { pub struct [<Workspace $name>] {
/// Monitor index (zero-indexed) /// Monitor index (zero-indexed)
monitor: usize, monitor: usize,
@@ -130,7 +139,7 @@ gen_workspace_subcommand_args! {
Tiling: #[enum] BooleanState Tiling: #[enum] BooleanState
} }
#[derive(Clap, Ahk)] #[derive(Clap, AhkFunction)]
struct Resize { struct Resize {
#[clap(arg_enum)] #[clap(arg_enum)]
edge: OperationDirection, edge: OperationDirection,
@@ -138,7 +147,7 @@ struct Resize {
sizing: Sizing, sizing: Sizing,
} }
#[derive(Clap, Ahk)] #[derive(Clap, AhkFunction)]
struct EnsureWorkspaces { struct EnsureWorkspaces {
/// Monitor index (zero-indexed) /// Monitor index (zero-indexed)
monitor: usize, monitor: usize,
@@ -150,7 +159,7 @@ macro_rules! gen_padding_subcommand_args {
// SubCommand Pattern // SubCommand Pattern
( $( $name:ident ),+ ) => { ( $( $name:ident ),+ ) => {
$( $(
#[derive(clap::Clap, derive_ahk::Ahk)] #[derive(clap::Clap, derive_ahk::AhkFunction)]
pub struct $name { pub struct $name {
/// Monitor index (zero-indexed) /// Monitor index (zero-indexed)
monitor: usize, monitor: usize,
@@ -172,7 +181,7 @@ macro_rules! gen_padding_adjustment_subcommand_args {
// SubCommand Pattern // SubCommand Pattern
( $( $name:ident ),+ ) => { ( $( $name:ident ),+ ) => {
$( $(
#[derive(clap::Clap, derive_ahk::Ahk)] #[derive(clap::Clap, derive_ahk::AhkFunction)]
pub struct $name { pub struct $name {
#[clap(arg_enum)] #[clap(arg_enum)]
sizing: Sizing, sizing: Sizing,
@@ -192,7 +201,7 @@ macro_rules! gen_application_target_subcommand_args {
// SubCommand Pattern // SubCommand Pattern
( $( $name:ident ),+ ) => { ( $( $name:ident ),+ ) => {
$( $(
#[derive(clap::Clap, derive_ahk::Ahk)] #[derive(clap::Clap, derive_ahk::AhkFunction)]
pub struct $name { pub struct $name {
#[clap(arg_enum)] #[clap(arg_enum)]
identifier: ApplicationIdentifier, identifier: ApplicationIdentifier,
@@ -209,7 +218,7 @@ gen_application_target_subcommand_args! {
IdentifyTrayApplication IdentifyTrayApplication
} }
#[derive(Clap, Ahk)] #[derive(Clap, AhkFunction)]
struct WorkspaceRule { struct WorkspaceRule {
#[clap(arg_enum)] #[clap(arg_enum)]
identifier: ApplicationIdentifier, identifier: ApplicationIdentifier,
@@ -228,7 +237,7 @@ struct Opts {
subcmd: SubCommand, subcmd: SubCommand,
} }
#[derive(Clap, Ahk)] #[derive(Clap, AhkLibrary)]
enum SubCommand { enum SubCommand {
/// Start komorebi.exe as a background process /// Start komorebi.exe as a background process
Start, Start,