Skip to content
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

Refactor kube-derive using darling #435

Merged
merged 4 commits into from
Feb 24, 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: 2 additions & 0 deletions kube-derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ quote = "1.0.8"
syn = { version = "1.0.57", features = ["extra-traits"] }
Inflector = "0.11.4"
serde_json = "1.0.61"
darling = "0.12.1"

[lib]
proc-macro = true
Expand All @@ -31,3 +32,4 @@ serde_yaml = "0.8.14"
k8s-openapi = { version = "0.11.0", default-features = false, features = ["v1_20"] }
schemars = { version = "0.8.0", features = ["chrono"] }
chrono = "0.4.19"
trybuild = "1.0"
742 changes: 309 additions & 433 deletions kube-derive/src/custom_resource.rs

Large diffs are not rendered by default.

40 changes: 1 addition & 39 deletions kube-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,46 +4,8 @@
#![recursion_limit = "1024"]
extern crate proc_macro;
#[macro_use] extern crate quote;
use proc_macro::TokenStream;
use syn::Result;

trait CustomDerive: Sized {
fn parse(input: syn::DeriveInput, tokens: proc_macro2::TokenStream) -> Result<Self>;
fn emit(self) -> Result<proc_macro2::TokenStream>;
}

fn run_custom_derive<T>(input: TokenStream) -> TokenStream
where
T: CustomDerive,
{
let input: proc_macro2::TokenStream = input.into();
let tokens = input.clone();
let token_stream = match syn::parse2(input)
.and_then(|input| <T as CustomDerive>::parse(input, tokens))
.and_then(<T as CustomDerive>::emit)
{
Ok(token_stream) => token_stream,
Err(err) => err.to_compile_error(),
};
token_stream.into()
}

trait ResultExt<T> {
fn spanning(self, spanned: impl quote::ToTokens) -> Result<T>;
}

impl<T, E> ResultExt<T> for std::result::Result<T, E>
where
E: std::fmt::Display,
{
fn spanning(self, spanned: impl quote::ToTokens) -> Result<T> {
self.map_err(|err| syn::Error::new_spanned(spanned, err))
}
}

// #[derive(CustomResource)]
mod custom_resource;
use custom_resource::CustomResource;

/// A custom derive for kubernetes custom resource definitions.
///
Expand Down Expand Up @@ -214,5 +176,5 @@ use custom_resource::CustomResource;
/// [`k8s_openapi::Resource`]: https://docs.rs/k8s-openapi/*/k8s_openapi/trait.Resource.html
#[proc_macro_derive(CustomResource, attributes(kube))]
pub fn derive_custom_resource(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
run_custom_derive::<CustomResource>(input)
custom_resource::derive(proc_macro2::TokenStream::from(input)).into()
}
10 changes: 10 additions & 0 deletions kube-derive/tests/test_ui.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Test that `kube-derive` outputs helpful error messages.
// If you make a change, remove `tests/ui/*.stderr` and run `cargo test`.
// Then copy the files that appear under `wip/` if it's what you expected.
// Alternatively, run `TRYBUILD=overwrite cargo test`.
// See /~https://github.com/dtolnay/trybuild
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perfect!

#[test]
fn test_failures() {
let t = trybuild::TestCases::new();
t.compile_fail("tests/ui/*.rs");
}
10 changes: 10 additions & 0 deletions kube-derive/tests/ui/enum_fails.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use kube_derive::CustomResource;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

#[derive(CustomResource, Serialize, Deserialize, Debug, Clone, JsonSchema)]
enum FooSpec {
Foo,
}

fn main() {}
5 changes: 5 additions & 0 deletions kube-derive/tests/ui/enum_fails.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: Enums or Unions can not #[derive(CustomResource)]
--> $DIR/enum_fails.rs:6:6
|
6 | enum FooSpec {
| ^^^^^^^
11 changes: 11 additions & 0 deletions kube-derive/tests/ui/fail_with_suggestion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use kube_derive::CustomResource;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

#[derive(CustomResource, Serialize, Deserialize, Debug, Clone, JsonSchema)]
#[kube(group = "clux.dev", version = "v1", kind = "Foo", shortnames = "foo")]
struct FooSpec {
foo: String,
}

fn main() {}
5 changes: 5 additions & 0 deletions kube-derive/tests/ui/fail_with_suggestion.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: Unknown field: `shortnames`. Did you mean `shortname`?
--> $DIR/fail_with_suggestion.rs:6:58
|
6 | #[kube(group = "clux.dev", version = "v1", kind = "Foo", shortnames = "foo")]
| ^^^^^^^^^^
10 changes: 10 additions & 0 deletions kube-derive/tests/ui/missing_required.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use kube_derive::CustomResource;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

#[derive(CustomResource, Serialize, Deserialize, Debug, Clone, JsonSchema)]
struct FooSpec {
foo: String,
}

fn main() {}
23 changes: 23 additions & 0 deletions kube-derive/tests/ui/missing_required.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
error: Missing field `group`
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shows errors from all the missing required attributes (not stopping at group anymore)

--> $DIR/missing_required.rs:5:10
|
5 | #[derive(CustomResource, Serialize, Deserialize, Debug, Clone, JsonSchema)]
| ^^^^^^^^^^^^^^
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: Missing field `version`
--> $DIR/missing_required.rs:5:10
|
5 | #[derive(CustomResource, Serialize, Deserialize, Debug, Clone, JsonSchema)]
| ^^^^^^^^^^^^^^
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: Missing field `kind`
--> $DIR/missing_required.rs:5:10
|
5 | #[derive(CustomResource, Serialize, Deserialize, Debug, Clone, JsonSchema)]
| ^^^^^^^^^^^^^^
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)