Skip to content

Commit 491d2b1

Browse files
committed
Add UI tests and more comments to procedural macro
1 parent 96c5d7e commit 491d2b1

19 files changed

+169
-20
lines changed

tests/tests/expand/simple-struct.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
use tsap::param;
2+
3+
#[param]
4+
#[derive(Debug)]
5+
struct SingleField<const C: bool> {
6+
value: f32,
7+
}
8+
9+
fn main() {}
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use tsap::param;
2+
3+
#[param]
4+
struct Param {
5+
no_const: u32
6+
}
7+
8+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: parameter sets should have a const boolean to indicate checking
2+
3+
= help: add a const boolean as your first generic
4+
5+
--> tests/ui/missing-const-generic.rs:4:1
6+
|
7+
4 | / struct Param {
8+
5 | | no_const: u32
9+
6 | | }
10+
| |_^
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use tsap::param;
2+
3+
#[param]
4+
enum Param<const C: bool> {
5+
NotSupported(f32, f32)
6+
}
7+
8+
fn main() {}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: we don't support variants with more than one field
2+
3+
= help: `#[params]' can only be used on enum with single field variants
4+
5+
--> tests/ui/multiple-enum-fields.rs:4:1
6+
|
7+
4 | / enum Param<const C: bool> {
8+
5 | | NotSupported(f32, f32)
9+
6 | | }
10+
| |_^

tests/tests/ui/named-enum-field.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use tsap::param;
2+
3+
#[param]
4+
enum Param<const C: bool> {
5+
NotSupported {
6+
value: f32,
7+
}
8+
}
9+
10+
fn main() {}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: named enum variants are not supported
2+
3+
= help: use unnamed variant
4+
5+
--> tests/ui/named-enum-field.rs:5:5
6+
|
7+
5 | / NotSupported {
8+
6 | | value: f32,
9+
7 | | }
10+
| |_____^
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use tsap::param;
2+
3+
#[param]
4+
enum Param<'a, const C: bool> {
5+
RandomForest,
6+
SVClassifier
7+
}
8+
9+
#[param]
10+
enum Param<T, const C: bool> {
11+
RandomForest(T),
12+
SVClassifier
13+
}
14+
15+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error: parameter sets should have a const boolean to indicate checking
2+
3+
= help: add a const boolean as your first generic
4+
5+
--> tests/ui/other-type-argument-first.rs:4:1
6+
|
7+
4 | / enum Param<'a, const C: bool> {
8+
5 | | RandomForest,
9+
6 | | SVClassifier
10+
7 | | }
11+
| |_^
12+
13+
error: parameter sets should have a const boolean to indicate checking
14+
15+
= help: add a const boolean as your first generic
16+
17+
--> tests/ui/other-type-argument-first.rs:10:1
18+
|
19+
10 | / enum Param<T, const C: bool> {
20+
11 | | RandomForest(T),
21+
12 | | SVClassifier
22+
13 | | }
23+
| |_^

tests/tests/ui/some-arguments.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use tsap::param;
2+
3+
#[param(should_not_have = "this")]
4+
struct Param<const C: bool> {
5+
no_const: u32
6+
}
7+
8+
fn main() {}

tests/tests/ui/some-arguments.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: this attribute takes no arguments
2+
3+
= help: use #[param]
4+
5+
--> tests/ui/some-arguments.rs:3:9
6+
|
7+
3 | #[param(should_not_have = "this")]
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^

tests/tests/ui/trait-not-allowed.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use tsap::param;
2+
3+
#[param]
4+
trait Param<const C: bool> {
5+
type Assoc;
6+
}
7+
8+
fn main() {}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: item is not a struct or enum
2+
3+
= help: `#[params]` can only be used on structs or enums
4+
5+
--> tests/ui/trait-not-allowed.rs:4:1
6+
|
7+
4 | / trait Param<const C: bool> {
8+
5 | | type Assoc;
9+
6 | | }
10+
| |_^

tsap/src/templates.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ impl Template for RunCommand {
8484
pub struct GlobPattern;
8585

8686
impl Template for GlobPattern {
87-
fn resolve(&mut self, key: String, _map: Table, field: toml::Value) -> Value {
87+
fn resolve(&mut self, _key: String, _map: Table, field: toml::Value) -> Value {
8888
let pattern = match field {
8989
Value::String(cmd) => cmd,
9090
_ => panic!("Glob pattern not a string!"),

tsap/src/toml_builder.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ fn merge(mut root: Value, action: Action) -> (Value, Vec<Action>) {
1616
let num = paths.len() - 1;
1717

1818
for path in &paths[..=num-1] {
19-
let local = match local {
19+
match local {
2020
Value::Table(ref mut t) if t.contains_key(path) =>
2121
local = t.get_mut(path).unwrap(),
2222
_ => return (root, vec![action])
@@ -170,7 +170,7 @@ impl TryFrom<toml::Value> for TomlBuilder {
170170
type Error = Error;
171171

172172
fn try_from(root: toml::Value) -> Result<TomlBuilder> {
173-
let mut builder = TomlBuilder {
173+
let builder = TomlBuilder {
174174
templates: Templates::default(),
175175
actions: Vec::new(),
176176
root,

tsap_macro/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ pub fn param(args: TokenStream, input: TokenStream) -> TokenStream {
2020
let item = parser::parse(args.into(), input.clone().into());
2121
let model = model::analyze(item);
2222
let ir = lower::Intermediate::lower(model.clone());
23-
let tokens = quote!(#ir);
2423

2524
#[cfg(feature="toml")]
2625
let res = {

tsap_macro/src/lower.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use syn::{Item, Ident};
1+
use syn::Ident;
22
use proc_macro2::TokenStream;
33
use quote::{quote, format_ident};
44

tsap_macro/src/lower_toml.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@ use crate::model::{Model, ModelFields};
55
#[derive(Debug)]
66
pub struct Intermediate {
77
pub(crate) item: TokenStream,
8-
pub(crate) builder: TokenStream,
98
pub(crate) impls: TokenStream,
109
}
1110

1211
impl Intermediate {
1312
pub(crate) fn lower(model: Model) -> Intermediate {
1413
let item2 = model.item_definition(Some(false));
1514

16-
let Model { name, check_name, item, fields, .. } = model;
15+
let Model { name, fields, .. } = model;
1716

1817
let builder_name = format_ident!("{}Builder", name);
1918
let builder = quote!(
@@ -35,7 +34,6 @@ impl Intermediate {
3534
let valname = format!("{}", name);
3635
let typ = typ.as_ref().unwrap();
3736
let arg_typ_false = typ.quote(Some(false));
38-
let arg_typ = typ.quote(None);
3937

4038
quote!(
4139
fn #name<F: FnOnce(#arg_typ_false) -> #arg_typ_false>(mut self, val: F) -> Self {
@@ -119,7 +117,6 @@ impl Intermediate {
119117

120118
Intermediate {
121119
item,
122-
builder: builder,
123120
impls: impls,
124121
}
125122
}

tsap_macro/src/model.rs

+27-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use syn::{Item, Ident, Type, Fields, GenericParam, FieldsUnnamed, PathArguments, AngleBracketedGenericArguments, GenericArgument, TypePath, punctuated::Punctuated, token::{Comma, Colon2}, PathSegment, TypeTraitObject, TypeParamBound, visit::{self, Visit}, visit_mut::{self, VisitMut}};
1+
use syn::{Item, Ident, Type, Fields, GenericParam, FieldsUnnamed, punctuated::Punctuated, token::Comma, PathSegment, visit::{self, Visit}, visit_mut::{self, VisitMut}};
22
use proc_macro_error::abort;
33
use quote::quote;
44
use proc_macro2::{TokenStream, Span};
@@ -33,30 +33,37 @@ impl VisitMut for ReplaceCheck {
3333
}
3434
}
3535

36+
/// Type of a field, either named in struct or unnamed in enums
37+
///
38+
/// Carries information whether we want to track check status of wrapped type
39+
/// in `const_name` optionality.
3640
#[derive(Debug, Clone)]
3741
pub struct ModelType {
3842
wrapped: Type,
3943
const_name: Option<Ident>,
4044
}
4145

4246
impl ModelType {
47+
/// Construct a field type with const generic parameter
48+
///
49+
/// Checks if const generic parameter exists in the wrapped type
4350
pub fn new(typ: &Type, const_name: &Ident) -> ModelType {
4451
let mut visitor = FindCheck { found: false, const_name };
4552
visitor.visit_type(typ);
4653

47-
if visitor.found {
48-
ModelType {
49-
wrapped: typ.clone(),
50-
const_name: Some(const_name.clone()),
51-
}
52-
} else {
53-
ModelType {
54-
wrapped: typ.clone(),
55-
const_name: None,
56-
}
54+
let const_name = match visitor.found {
55+
true => Some(const_name.clone()),
56+
false => None,
57+
};
58+
59+
ModelType {
60+
wrapped: typ.clone(),
61+
const_name,
5762
}
5863
}
5964

65+
/// Create a token stream from the type and fills in definitions of const
66+
/// generic parameter
6067
pub fn quote(&self, checked: Option<bool>) -> TokenStream {
6168
if let Some(const_name) = &self.const_name {
6269
let check_param = match checked {
@@ -77,11 +84,18 @@ impl ModelType {
7784
}
7885
}
7986

87+
/// Contains const generic in field type
8088
pub fn has_const_name(&self) -> bool {
8189
self.const_name.is_some()
8290
}
8391
}
8492

93+
/// Fields of annotated structures
94+
///
95+
/// We only support single, unnamed field in enum variants and named structure
96+
/// fields. For named enum variants the inner definition should go in a separate
97+
/// struct. For unnamed struct variants no useful composition function names can
98+
/// be derived. Traits are not supported.
8599
#[derive(Debug, Clone)]
86100
pub enum ModelFields {
87101
Enum(Vec<(Ident, Option<ModelType>)>),
@@ -98,6 +112,7 @@ pub struct Model {
98112
}
99113

100114
impl Model {
115+
/// Return argument parameters of item
101116
pub(crate) fn param_args(&self) -> Punctuated<Ident, Comma> {
102117
self.rem_param_types.iter()
103118
.map(|x| match x {
@@ -108,6 +123,7 @@ impl Model {
108123
.collect()
109124
}
110125

126+
/// Return item definition with filled-in checked parameter
111127
pub(crate) fn item_definition(&self, checked: Option<bool>) -> TokenStream {
112128
let check_param = match checked {
113129
Some(true) => Ident::new("true", Span::call_site()),

0 commit comments

Comments
 (0)