1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851
//! Basicly clap for attribute macros:
//! ```
//! # use attribute_derive::Attribute;
//! # use syn::Type;
//! #[derive(Attribute)]
//! #[attribute(ident = collection)]
//! #[attribute(error(missing_field = "`{field}` was not specified"))]
//! struct CollectionAttribute {
//! // Options are optional by default (will be set to None if not specified)
//! authority: Option<String>,
//! name: String,
//! // Any type implementing default can be flagged as default
//! // This will be set to Vec::default() when not specified
//! #[attribute(optional)]
//! views: Vec<Type>,
//! // Booleans can be used without assiging a value. as a flag.
//! // If omitted they are set to false
//! some_flag: bool,
//! }
//! ```
//!
//! Will be able to parse an attribute like this:
//! ```text
//! #[collection(authority="Some String", name = r#"Another string"#, views = [Option, ()])]
//! ```
//!
//! Any type that [`ConvertParsed`] is implemented for is supported. These
//! should be the general types that syn supports like [`LitStr`](struct@LitStr)
//! or [`Type`] or that have a direct equivalent in those like [`String`],
//! [`char`] or [`f32`]. A special treatment have [`Vecs`](Vec) which are parsed
//! using [`Array`] with the syntax `[a, b, c]` and [`Options`](Option) that
//! will be [`None`] if not specified and [`Some`] when the value is specified
//! via the attribute. It is not specified via `Some(value)` but as just
//! `value`.
//!
//! # Attributes
//!
//! The parsing of attributes can be modified with the following parameters via
//! the `#[attribute(<params>)]` attribute. All of them are optional. Error
//! messages are formatted using [interpolator], and only support display and on
//! lists `i` formatting. See [interpolator] docs for details.
//!
//! ### Struct
//!
//! - `ident = <ident>` The attribute ident. Improves error messages and enables
//! the [`from_attributes`](Attribute::from_attributes) and
//! [`remove_attributes`](Attribute::remove_attributes) functions.
//! - `aliases = [<alias>, ...]` Aliases for the attribute ident.
//! - `error = "<error message>"` Overrides default error message.
//! - `error(`
//! - ``unknown_field = "supported fields are {expected_fields:i..-1(`{}`)(,
//! )} and `{expected_fields:i-1}`",`` Custom error message printed if an
//! unknown property is specified and attribute has more than one field.
//! Supports `{found_field}` and `{expected_fields:i}` placeholders.
//! - ``unknown_field_single = "expected supported field
//! `{expected_field}`",`` Custom error message printed if an unknown
//! property is specified, and attribute only has a single field. Supports
//! `{found_field}` and `{expected_field}` placeholders.
//! - ``unknown_field_empty = "expected empty attribute",`` Custom error
//! message printed if a property is specified, and attribute has no
//! fields. Supports `{found_field}` placeholder.
//! - ``duplicate_field = "`{field}` is specified multiple times",`` Custom
//! error message printed if a property is specified multiple times.
//! Supports `{field}` placeholder.
//! - ``missing_field = "required `{field}` is not specified",`` Custom
//! error message printed if a required property is not specified.
//! Supports `{field}` placeholder.
//! - ``field_help = "try `#[{attribute}({field}={example})]`",`` Additional
//! help message printed if a required property is not specified or has an
//! error. Supports `{attribute}`, `{field}` and `{example}` placeholder.
//! - ``missing_flag = "required `{flag}` is not specified",`` Custom error
//! message printed if a required flag is not specified. Supports `{flag}`
//! placeholder.
//! - ``flag_help = "try `#[{attribute}({flag})]`",`` Additional help
//! message printed if a required flag is not specified. Supports
//! `{attribute}` and `{flag}` placeholder.
//! - ``conflict = "`{first}` conflicts with mutually exclusive
//! `{second}`"`` Custom error message printed if conflicting properties
//! are specified. Supports `{first}` and `{second}` placeholder.
//!
//! `)`
// //! - `duplicate = AggregateOrError` Change the behavior for duplicate arguments
// //! (also across multiple attributes).
// //! - `AggregateOrError` Aggregate multiple [`Vec`], error on everything else.
// //! - `Error` Disables aggregation, errors on all duplicates.
// //! - `AggregateOrOverride` Aggregate multiple [`Vec`], take the last
// //! specified for everything else.
// //! - `Override` Disables aggregation, always take the last value.
//! ### Fields
//!
//! - `optional` / `optional = true` If field is not specified, the default
//! value is used instead.
//! - `optional = false` Disables implicit optionality of [`Option`], [`Vec`]
//! and [`bool`]. Note that this makes `Option<T>` behave the same as `T` and
//! makes a bool a mandatory flag.
//! - `default = <default expr>` provides a default to be used instead of
//! [`Default`]. Enables `optional`.
// //! - `aggregate = false` Disables aggregation for [`Vec`].
// //! - `flag = false` Disables flag mode for bool.
//! - `conflicts = [<field>, ...]` Conflicting fields
//! - `example = "<example>"`
//!
//! # Limitations
//!
//! There are some limitations in syntax parsing that will be lifted in future
//! releases.
//!
//! - literals in top level (meaning something like `#[attr(42, 3.14, "hi")]`
//! - function like arguments (something like `#[attr(view(a = "test"))]`
//! - other syntaxes, maybe something like `key: value`
//!
//! # Parse methods
//!
//! There are multiple ways of parsing a struct deriving [`Attribute`].
//!
//! For helper attributes there is:
//! - [`Attribute::from_attributes`] which takes in an [`IntoIterator<Item = &'a
//! syn::Attribute`](syn::Attribute)
//! (e.g. a [`&Vec<syn::Attribute>`](syn::Attribute)). Most useful for derive
//! macros.
//! - [`Attribute::remove_attributes`] which takes an [`&mut
//! Vec<syn::Attribute>`](syn::Attribute)
//! and does not only parse the [`Attribute`] but also removes those matching.
//! Useful for helper attributes for proc macros, where the helper attributes
//! need to be removed.
//!
//! For parsing a single [`TokenStream`] e.g. for parsing the proc macro input
//! there a two ways:
//!
//! - [`Attribute::from_args`] taking in a [`TokenStream`]
//! - As `derive(Attribute)` also derives [`Parse`] so you can use the
//! [parse](mod@syn::parse) API,
//! e.g. with [`parse_macro_input!(tokens as
//! Attribute)`](syn::parse_macro_input!).
//!
//! [interpolator]: https://docs.rs/interpolator/latest/interpolator/
#![deny(missing_docs)]
use std::fmt::Display;
#[doc(hidden)]
pub use attribute_derive_macro::Attribute;
use proc_macro2::{Group, Literal, Punct, Span, TokenStream, TokenTree};
use quote::ToTokens;
use syn::parse::{Parse, Result};
use syn::punctuated::Punctuated;
use syn::token::{
Abstract, And, AndAnd, AndEq, As, Async, At, Auto, Await, Become, Break, Caret, CaretEq, Colon,
Comma, Const, Continue, Crate, Do, Dollar, Dot, DotDot, DotDotDot, DotDotEq, Dyn, Else, Enum,
Eq, EqEq, Extern, FatArrow, Final, Fn, For, Ge, Gt, If, Impl, In, LArrow, Le, Let, Loop, Lt,
Match, Minus, MinusEq, Mod, Move, Mut, Ne, Not, Or, OrEq, OrOr, Override, PathSep, Percent,
PercentEq, Plus, PlusEq, Pound, Priv, Pub, Question, RArrow, Ref, Return, SelfType, SelfValue,
Semi, Shl, ShlEq, Shr, ShrEq, Slash, SlashEq, Star, StarEq, Static, Struct, Super, Tilde,
Trait, Try, Typeof, Underscore, Union, Unsafe, Unsized, Use, Virtual, Where, While, Yield,
};
use syn::{
bracketed, parse2, parse_quote, Abi, AngleBracketedGenericArguments, BareFnArg, BinOp,
BoundLifetimes, ConstParam, Constraint, DeriveInput, Expr, ExprArray, ExprAssign, ExprAsync,
ExprBinary, ExprBlock, ExprBreak, ExprCall, ExprCast, ExprClosure, ExprContinue, ExprField,
ExprForLoop, ExprIf, ExprIndex, ExprLet, ExprLit, ExprLoop, ExprMacro, ExprMatch,
ExprMethodCall, ExprParen, ExprPath, ExprRange, ExprReference, ExprRepeat, ExprReturn,
ExprStruct, ExprTry, ExprTryBlock, ExprTuple, ExprUnary, ExprUnsafe, ExprWhile, ExprYield,
FieldsNamed, FieldsUnnamed, GenericArgument, GenericParam, Generics, Ident, Index, Lifetime,
Lit, LitBool, LitByteStr, LitChar, LitFloat, LitInt, LitStr, Member, Meta, MetaList,
MetaNameValue, ParenthesizedGenericArguments, Path, PathSegment, ReturnType, Token, TraitBound,
TraitBoundModifier, Type, TypeArray, TypeBareFn, TypeGroup, TypeImplTrait, TypeInfer,
TypeMacro, TypeNever, TypeParam, TypeParamBound, TypeParen, TypePath, TypePtr, TypeReference,
TypeSlice, TypeTraitObject, TypeTuple, UnOp, Variant, Visibility, WhereClause, WherePredicate,
};
#[doc(hidden)]
pub mod __private {
pub use {proc_macro2, quote, syn};
}
/// Helper trait providing the path for an attribute.
///
/// Automatically derived with [`Attribute`], if `#[attribute(ident =
/// "some_ident")]` is provided.
pub trait AttributeIdent: Sized {
/// Type used for Self::ALIASES, e.g. `[&'static str; 5]`
type IDENTS: AsRef<[&'static str]>;
/// List of idents
const IDENTS: Self::IDENTS;
/// Tests if Attribute matches one of the idents
fn is_ident(path: &Path) -> bool {
Self::IDENTS
.as_ref()
.iter()
.any(|ident| path.is_ident(ident))
}
}
/// The trait you actually derive on your attribute struct.
///
/// Basic gist is a struct like this:
/// ```
/// # use attribute_derive::Attribute;
/// # use syn::Type;
/// #[derive(Attribute)]
/// #[attribute(ident = collection)]
/// #[attribute(error(missing_field = "`{field}` was not specified"))]
/// struct CollectionAttribute {
/// // Options are optional by default (will be set to None if not specified)
/// authority: Option<String>,
/// name: String,
/// // Any type implementing default can be flagged as default
/// // This will be set to Vec::default() when not specified
/// #[attribute(optional)]
/// views: Vec<Type>,
/// // Booleans can be used without assiging a value. as a flag.
/// // If omitted they are set to false
/// some_flag: bool,
/// }
/// ```
///
/// Will be able to parse an attribute like this:
/// ```text
/// #[collection(authority="Some String", name = r#"Another string"#, views = [Option, ()], some_flag)]
/// ```
pub trait Attribute: Sized {
/// Helper struct for storing and parsing attributes
type Parser: TryExtendOne + Parse + Default;
/// Handles conversion from `Parser` used by the other functions internally
fn from_parser(parser: Self::Parser) -> Result<Self>;
/// Parses an [`IntoIterator`] of [`syn::Attributes`](syn::Attribute) e.g.
/// [`Vec<Attribute>`](Vec). Only availible if you specify the attribute
/// ident: `#[attribute(ident="<ident>")]` when using the derive macro.
///
/// It can therefore parse fields set over multiple attributes like:
/// ```text
/// #[collection(authority = "Authority", name = "Name")]
/// #[collection(views = [A, B])]
/// ```
/// and also catch duplicate/conflicting settings over those.
///
/// This is best used for derive macros, where you don't need to remove your
/// attributes.
///
/// # Errors
/// Fails with a [`syn::Error`] so you can conveniently return that as a
/// compiler error in a proc macro in the following cases
///
/// - A necessary parameter is omitted
/// - Invalid input is given for a parameter
/// - A non aggregating parameter is specified multiple times
/// - An attribute called [`IDENTS`](const@AttributeIdent::IDENTS) has
/// invalid syntax (e.g. `#attr(a: "a")`)
fn from_attributes<'a>(attrs: impl IntoIterator<Item = &'a syn::Attribute>) -> Result<Self>
where
Self: AttributeIdent,
{
attrs
.into_iter()
.filter_map(|attr| {
Self::is_ident(&attr.path()).then(|| attr.parse_args::<Self::Parser>())
})
.try_fold(Self::Parser::default(), |mut acc, item| {
acc.try_extend_one(item?)?;
Ok(acc)
})
.and_then(Self::from_parser)
}
/// Parses an [`&mut Vec<syn::Attributes>`](syn::Attribute). Removing
/// matching attributes. Only availible if you specify an ident:
/// `#[attribute(ident="<ident>")]` when using the derive macro.
///
/// It can therefore parse fields set over multiple attributes like:
/// ```text
/// #[collection(authority = "Authority", name = "Name")]
/// #[collection(views = [A, B])]
/// ```
/// and also catch duplicate/conflicting settings over those.
///
/// Use this if you are implementing an attribute macro, and need to remove
/// your helper attributes.
///
/// # Errors
/// Fails with a [`syn::Error`] so you can conveniently return that as a
/// compiler error in a proc macro in the following cases
///
/// - A necessary parameter is omitted
/// - Invalid input is given for a parameter
/// - A non aggregating parameter is specified multiple times
/// - An attribute called [`IDENTS`](const@AttributeIdent::IDENTS) has
/// invalid syntax (e.g. `#attr(a: "a")`)
fn remove_attributes(attrs: &mut Vec<syn::Attribute>) -> Result<Self>
where
Self: AttributeIdent,
{
let mut parser: Self::Parser = Default::default();
let mut i = 0;
while i < attrs.len() {
if Self::is_ident(&attrs[i].path()) {
parser.try_extend_one(attrs.remove(i).parse_args()?)?;
} else {
i += 1;
}
}
Self::from_parser(parser)
}
/// Parses a [`TokenStream`](proc_macro2::TokenStream).
///
/// Useful for implementing general proc macros to parse the input of your
/// macro.
///
/// Due to this only parsing the input for a single attribute it is not able
/// to aggregate input spread over multiple attributes.
///
/// # Errors
/// Fails with a [`syn::Error`] so you can conveniently return that as a
/// compiler error in a proc macro in the following cases
///
/// - A necessary parameter is omitted
/// - Invalid input is given for a parameter
/// - A non aggregating parameter is specified multiple times
fn from_args(tokens: TokenStream) -> Result<Self> {
parse2(tokens).and_then(Self::from_parser)
}
}
/// Trait to join two structs of the same type
pub trait TryExtendOne {
/// Try to extend self with another Self, failing if there are conflicts
fn try_extend_one(&mut self, other: Self) -> Result<()>;
}
/// Helper trait to convert syn types implementing [`Parse`] like
/// [`LitStr`](struct@LitStr) to rust types like [`String`]
///
/// You probably don't need to implement this trait, as most syn types like
/// [`LitStr`](struct@LitStr) and [`Type`] or that have a direct equivalent in
/// those like [`String`], [`char`] or [`f32`] are already implemented. A
/// special treatment have [`Vecs`](Vec) which are parsed using the helper
/// [`Array`] with the syntax `[a, b, c]` and [`Options`](Option) that will be
/// [`None`] if not specified and [`Some`] when the value is specified via the
/// attribute. It is not specified via `Some(value)` but as just `value`.
pub trait ConvertParsed
where
Self: Sized,
Self::Type: Error,
{
/// The type this can be converted from
type Type;
/// This takes [`Self::Type`] and converts it to [`Self`].
///
/// This can return an error, e.g. when parsing an integer too large for a
/// [`u8`] into an `u8`
fn convert(value: Self::Type) -> Result<Self>;
/// Should values of this type return their default when they are not
/// specified even when the `default` flag is not specified (only
/// returns `true` for [`Option`], [`Vec`] and [`bool`] currently)
fn default_by_default() -> bool {
false
}
/// The default value, this is necessary to implement the implicit default
/// behavior of [`Option`] and [`bool`].
///
/// This is necessary as the [`Default`] trait cannot be used in expanded
/// code, but normally you can easily implement it using it:
/// ```
/// # use attribute_derive::ConvertParsed;
/// # use syn::{Result, LitBool};
/// # #[derive(Default)]
/// # struct bool;
/// impl ConvertParsed for bool {
/// # type Type = LitBool;
/// # fn convert(value: Self::Type) -> Result<Self> {
/// # unimplemented!()
/// # }
/// fn default() -> Self {
/// Default::default()
/// }
/// }
/// ```
fn default() -> Self {
unreachable!("default_by_default should only return true if this is overridden")
}
/// Returns the value when this type is specified as flag i.e. just
/// `#[attr(default)]` instead of `#[attr(default=true)]`. This relies
/// on [`Self::default`].
fn as_flag() -> Option<Self::Type> {
None
}
/// Should values of this type be aggregated instead of conflict if
/// specified multiple times
///
/// Currently this is only implemented for [`Arrays`](Array)
#[allow(unused)]
fn aggregate(
this: Option<IdentValue<Self::Type>>,
other: Option<IdentValue<Self::Type>>,
error_msg: &str,
) -> Result<Option<IdentValue<Self::Type>>> {
match (this, other) {
(None, value) => Ok(value),
(value, None) => Ok(value),
(Some(this), Some(other)) => {
let mut error = this.ident.error(error_msg);
syn::Error::combine(&mut error, other.ident.error(error_msg));
Err(error)
}
}
}
}
/// Helper trait to generate sensible errors
pub trait Error {
/// This is used to be able to create errors more easily. Mostly used
/// through the implementation for [`T: ToTokens`](ToTokens).
fn error(&self, message: impl Display) -> syn::Error;
}
impl<T> Error for T
where
T: ToTokens,
{
fn error(&self, message: impl Display) -> syn::Error {
syn::Error::new_spanned(self, message)
}
}
/// Helper struct to hold a value and the ident of its property
pub struct IdentValue<T> {
/// The value
pub value: T,
/// The ident
pub ident: Ident,
}
/// Macro to easily implement [`ConvertParsed`] for syn types
macro_rules! convert_parsed {
($(#[$meta:meta])* $type:path) => {
$(#[$meta])*
impl ConvertParsed for $type {
type Type = $type;
fn convert(s: Self) -> Result<Self> {
Ok(s)
}
}
};
[$($type:path),* $(,)?] => {
$(
impl ConvertParsed for $type {
type Type = $type;
fn convert(s: Self) -> Result<Self> {
Ok(s)
}
}
)*
};
($from:path => $to:path) => {
impl ConvertParsed<$from> for $to {
fn convert(value: $from) -> Result<$to> {
Ok(value.into())
}
}
};
($from:path => $($to:path),+ : $with:path ) => {
$(
impl ConvertParsed for $to {
type Type = $from;
fn convert(value: $from) -> Result<$to> {
Ok($with(&value))
}
}
)*
};
($from:path => $($to:path),+ :? $with:path ) => {
$(
impl ConvertParsed for $to {
type Type = $from;
fn convert(value: $from) -> Result<$to> {
$with(&value)
}
}
)*
};
}
impl<Output, Parsed> ConvertParsed for Option<Output>
where
Output: ConvertParsed<Type = Parsed>,
Parsed: Error + Clone,
{
type Type = Parsed;
fn convert(s: Parsed) -> Result<Self> {
Ok(Some(ConvertParsed::convert(s)?))
}
fn default_by_default() -> bool {
true
}
fn default() -> Self {
Default::default()
}
}
impl<Output, Parsed> ConvertParsed for Vec<Output>
where
Output: ConvertParsed<Type = Parsed>,
Parsed: Clone,
{
type Type = Array<Parsed>;
fn convert(array: Array<Parsed>) -> Result<Self> {
array.data.into_iter().map(ConvertParsed::convert).collect()
}
fn aggregate(
this: Option<IdentValue<Self::Type>>,
other: Option<IdentValue<Self::Type>>,
_: &str,
) -> Result<Option<IdentValue<Self::Type>>> {
Ok(match (this, other) {
(None, None) => None,
(None, value) => value,
(value, None) => value,
(Some(mut this), Some(other)) => {
this.value.data.extend_from_slice(&other.value.data);
this.value.span = this
.value
.span
.join(other.value.span)
.unwrap_or(this.value.span);
// TODO figure out what to do with the idents
Some(this)
}
})
}
}
impl ConvertParsed for bool {
type Type = LitBool;
fn convert(value: Self::Type) -> Result<Self> {
Ok(value.value)
}
fn default_by_default() -> bool {
true
}
fn default() -> Self {
false
}
fn as_flag() -> Option<Self::Type> {
Some(parse_quote!(true))
}
}
/// Helper struct to parse array literals:
/// `[a, b, c]`
#[derive(Clone)]
pub struct Array<T> {
data: Vec<T>,
span: Span,
}
impl<T> Parse for Array<T>
where
T: Parse,
{
fn parse(input: syn::parse::ParseStream) -> Result<Self> {
let content;
let b = bracketed!(content in input);
let i = Punctuated::<T, Token!(,)>::parse_terminated(&content)?;
Ok(Self {
data: i.into_iter().collect(),
span: b.span.join(),
})
}
}
impl<T> Error for Array<T> {
fn error(&self, message: impl Display) -> syn::Error {
syn::Error::new(self.span, message)
}
}
convert_parsed!(Type);
convert_parsed!(Path);
convert_parsed!(Lit);
convert_parsed![LitStr, LitByteStr, LitChar, LitInt, LitFloat, LitBool];
convert_parsed!(Expr);
convert_parsed![TokenTree, Group, Punct, Literal];
// TODO make this warning better visable
convert_parsed! {
/// Try to avoid using this, as it will consume everything behind, so it needs to be defined as the
/// last parameter.
///
/// In the future there might be something to allow better handling of this (maybe by putting it
/// into `()`)
TokenStream
}
convert_parsed!(LitStr => String: LitStr::value);
// TODO convert_parsed!(LitByteStr => Vec<u8>: LitByteStr::value);
convert_parsed!(LitChar => char: LitChar::value);
convert_parsed!(LitInt => u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize:? LitInt::base10_parse);
convert_parsed!(LitFloat => f32, f64:? LitFloat::base10_parse);
// Some probably useless stuff
convert_parsed![
Abi,
Abstract,
Plus,
PlusEq,
And,
AndAnd,
AndEq,
AngleBracketedGenericArguments,
As,
Async,
At,
Auto,
Await,
Not,
BareFnArg,
Become,
BinOp,
BoundLifetimes,
Break,
Caret,
CaretEq,
Colon,
PathSep,
Comma,
Const,
ConstParam,
Constraint,
Continue,
Crate,
DeriveInput,
Slash,
SlashEq,
Do,
Dollar,
Dot,
DotDot,
DotDotDot,
DotDotEq,
Dyn,
Else,
Enum,
Eq,
EqEq,
ExprArray,
ExprAssign,
ExprAsync,
ExprBinary,
ExprBlock,
ExprBreak,
ExprCall,
ExprCast,
ExprClosure,
ExprContinue,
ExprField,
ExprForLoop,
ExprIf,
ExprIndex,
ExprLet,
ExprLit,
ExprLoop,
ExprMacro,
ExprMatch,
ExprMethodCall,
ExprParen,
ExprPath,
ExprRange,
ExprReference,
ExprRepeat,
ExprReturn,
ExprStruct,
ExprTry,
ExprTryBlock,
ExprTuple,
ExprUnary,
ExprUnsafe,
ExprWhile,
ExprYield,
Extern,
FatArrow,
FieldsNamed,
FieldsUnnamed,
Final,
Fn,
For,
Ge,
GenericArgument,
GenericParam,
Generics,
Gt,
Ident,
If,
Impl,
In,
Index,
LArrow,
Le,
Let,
Lifetime,
Loop,
Lt,
Match,
Member,
Meta,
MetaList,
MetaNameValue,
Mod,
Move,
StarEq,
Mut,
Ne,
Or,
OrEq,
OrOr,
Override,
ParenthesizedGenericArguments,
PathSegment,
Pound,
Priv,
Pub,
Question,
RArrow,
Ref,
Percent,
PercentEq,
Return,
ReturnType,
SelfType,
SelfValue,
Semi,
Shl,
ShlEq,
Shr,
ShrEq,
Star,
Static,
Struct,
Minus,
MinusEq,
Super,
Tilde,
Trait,
TraitBound,
TraitBoundModifier,
Try,
TypeArray,
TypeBareFn,
TypeGroup,
TypeImplTrait,
TypeInfer,
TypeMacro,
TypeNever,
TypeParam,
TypeParamBound,
TypeParen,
TypePath,
TypePtr,
TypeReference,
TypeSlice,
TypeTraitObject,
TypeTuple,
Typeof,
UnOp,
Underscore,
Union,
Unsafe,
Unsized,
Use,
Variant,
Virtual,
Visibility,
Where,
WhereClause,
WherePredicate,
While,
Yield,
syn::Macro,
syn::token::Box,
syn::token::Default,
syn::token::Macro,
syn::token::Type,
];
#[cfg(feature = "syn-full")]
mod syn_full {
use syn::{
Arm, Block, FieldValue, File, FnArg, ForeignItem, ForeignItemFn, ForeignItemMacro,
ForeignItemStatic, ForeignItemType, ImplItem, ImplItemConst, ImplItemMacro, ImplItemType,
Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro,
ItemMod, ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse,
Label, Pat, RangeLimits, Receiver, Signature, Stmt, TraitItem, TraitItemConst,
TraitItemMacro, TraitItemType, UseTree,
};
use super::*;
convert_parsed![
Arm,
Block,
FieldValue,
File,
FnArg,
ForeignItem,
ForeignItemFn,
ForeignItemMacro,
ForeignItemStatic,
ForeignItemType,
ImplItem,
ImplItemConst,
ImplItemMacro,
ImplItemType,
Item,
ItemConst,
ItemEnum,
ItemExternCrate,
ItemFn,
ItemForeignMod,
ItemImpl,
ItemMacro,
ItemMod,
ItemStatic,
ItemStruct,
ItemTrait,
ItemTraitAlias,
ItemType,
ItemUnion,
ItemUse,
Label,
Pat,
RangeLimits,
Receiver,
Signature,
Stmt,
TraitItem,
TraitItemConst,
TraitItemMacro,
TraitItemType,
UseTree,
];
}