use crate::algorithm::Printer;
use crate::iter::IterDelimited;
use crate::path::PathKind;
use crate::INDENT;
use proc_macro2::TokenStream;
use syn::{
Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemMacro, ForeignItemStatic,
ForeignItemType, ImplItem, ImplItemConst, ImplItemFn, ImplItemMacro, ImplItemType, Item,
ItemConst, ItemEnum, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro, ItemMod,
ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, Receiver,
Signature, StaticMutability, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro,
TraitItemType, Type, UseGlob, UseGroup, UseName, UsePath, UseRename, UseTree, Variadic,
};
impl Printer {
pub fn item(&mut self, item: &Item) {
match item {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
Item::Const(item) => self.item_const(item),
Item::Enum(item) => self.item_enum(item),
Item::ExternCrate(item) => self.item_extern_crate(item),
Item::Fn(item) => self.item_fn(item),
Item::ForeignMod(item) => self.item_foreign_mod(item),
Item::Impl(item) => self.item_impl(item),
Item::Macro(item) => self.item_macro(item),
Item::Mod(item) => self.item_mod(item),
Item::Static(item) => self.item_static(item),
Item::Struct(item) => self.item_struct(item),
Item::Trait(item) => self.item_trait(item),
Item::TraitAlias(item) => self.item_trait_alias(item),
Item::Type(item) => self.item_type(item),
Item::Union(item) => self.item_union(item),
Item::Use(item) => self.item_use(item),
Item::Verbatim(item) => self.item_verbatim(item),
_ => unimplemented!("unknown Item"),
}
}
fn item_const(&mut self, item: &ItemConst) {
self.outer_attrs(&item.attrs);
self.cbox(0);
self.visibility(&item.vis);
self.word("const ");
self.ident(&item.ident);
self.generics(&item.generics);
self.word(": ");
self.ty(&item.ty);
self.word(" = ");
self.neverbreak();
self.expr(&item.expr);
self.word(";");
self.end();
self.hardbreak();
}
fn item_enum(&mut self, item: &ItemEnum) {
self.outer_attrs(&item.attrs);
self.cbox(INDENT);
self.visibility(&item.vis);
self.word("enum ");
self.ident(&item.ident);
self.generics(&item.generics);
self.where_clause_for_body(&item.generics.where_clause);
self.word("{");
self.hardbreak_if_nonempty();
for variant in &item.variants {
self.variant(variant);
self.word(",");
self.hardbreak();
}
self.offset(-INDENT);
self.end();
self.word("}");
self.hardbreak();
}
fn item_extern_crate(&mut self, item: &ItemExternCrate) {
self.outer_attrs(&item.attrs);
self.visibility(&item.vis);
self.word("extern crate ");
self.ident(&item.ident);
if let Some((_as_token, rename)) = &item.rename {
self.word(" as ");
self.ident(rename);
}
self.word(";");
self.hardbreak();
}
fn item_fn(&mut self, item: &ItemFn) {
self.outer_attrs(&item.attrs);
self.cbox(INDENT);
self.visibility(&item.vis);
self.signature(&item.sig);
self.where_clause_for_body(&item.sig.generics.where_clause);
self.word("{");
self.hardbreak_if_nonempty();
self.inner_attrs(&item.attrs);
for stmt in &item.block.stmts {
self.stmt(stmt);
}
self.offset(-INDENT);
self.end();
self.word("}");
self.hardbreak();
}
fn item_foreign_mod(&mut self, item: &ItemForeignMod) {
self.outer_attrs(&item.attrs);
self.cbox(INDENT);
if item.unsafety.is_some() {
self.word("unsafe ");
}
self.abi(&item.abi);
self.word("{");
self.hardbreak_if_nonempty();
self.inner_attrs(&item.attrs);
for foreign_item in &item.items {
self.foreign_item(foreign_item);
}
self.offset(-INDENT);
self.end();
self.word("}");
self.hardbreak();
}
fn item_impl(&mut self, item: &ItemImpl) {
self.outer_attrs(&item.attrs);
self.cbox(INDENT);
self.ibox(-INDENT);
self.cbox(INDENT);
if item.defaultness.is_some() {
self.word("default ");
}
if item.unsafety.is_some() {
self.word("unsafe ");
}
self.word("impl");
self.generics(&item.generics);
self.end();
self.nbsp();
if let Some((negative_polarity, path, _for_token)) = &item.trait_ {
if negative_polarity.is_some() {
self.word("!");
}
self.path(path, PathKind::Type);
self.space();
self.word("for ");
}
self.ty(&item.self_ty);
self.end();
self.where_clause_for_body(&item.generics.where_clause);
self.word("{");
self.hardbreak_if_nonempty();
self.inner_attrs(&item.attrs);
for impl_item in &item.items {
self.impl_item(impl_item);
}
self.offset(-INDENT);
self.end();
self.word("}");
self.hardbreak();
}
fn item_macro(&mut self, item: &ItemMacro) {
self.outer_attrs(&item.attrs);
let semicolon = true;
self.mac(&item.mac, item.ident.as_ref(), semicolon);
self.hardbreak();
}
fn item_mod(&mut self, item: &ItemMod) {
self.outer_attrs(&item.attrs);
self.cbox(INDENT);
self.visibility(&item.vis);
if item.unsafety.is_some() {
self.word("unsafe ");
}
self.word("mod ");
self.ident(&item.ident);
if let Some((_brace, items)) = &item.content {
self.word(" {");
self.hardbreak_if_nonempty();
self.inner_attrs(&item.attrs);
for item in items {
self.item(item);
}
self.offset(-INDENT);
self.end();
self.word("}");
} else {
self.word(";");
self.end();
}
self.hardbreak();
}
fn item_static(&mut self, item: &ItemStatic) {
self.outer_attrs(&item.attrs);
self.cbox(0);
self.visibility(&item.vis);
self.word("static ");
self.static_mutability(&item.mutability);
self.ident(&item.ident);
self.word(": ");
self.ty(&item.ty);
self.word(" = ");
self.neverbreak();
self.expr(&item.expr);
self.word(";");
self.end();
self.hardbreak();
}
fn item_struct(&mut self, item: &ItemStruct) {
self.outer_attrs(&item.attrs);
self.cbox(INDENT);
self.visibility(&item.vis);
self.word("struct ");
self.ident(&item.ident);
self.generics(&item.generics);
match &item.fields {
Fields::Named(fields) => {
self.where_clause_for_body(&item.generics.where_clause);
self.word("{");
self.hardbreak_if_nonempty();
for field in &fields.named {
self.field(field);
self.word(",");
self.hardbreak();
}
self.offset(-INDENT);
self.end();
self.word("}");
}
Fields::Unnamed(fields) => {
self.fields_unnamed(fields);
self.where_clause_semi(&item.generics.where_clause);
self.end();
}
Fields::Unit => {
self.where_clause_semi(&item.generics.where_clause);
self.end();
}
}
self.hardbreak();
}
fn item_trait(&mut self, item: &ItemTrait) {
self.outer_attrs(&item.attrs);
self.cbox(INDENT);
self.visibility(&item.vis);
if item.unsafety.is_some() {
self.word("unsafe ");
}
if item.auto_token.is_some() {
self.word("auto ");
}
self.word("trait ");
self.ident(&item.ident);
self.generics(&item.generics);
for supertrait in item.supertraits.iter().delimited() {
if supertrait.is_first {
self.word(": ");
} else {
self.word(" + ");
}
self.type_param_bound(&supertrait);
}
self.where_clause_for_body(&item.generics.where_clause);
self.word("{");
self.hardbreak_if_nonempty();
self.inner_attrs(&item.attrs);
for trait_item in &item.items {
self.trait_item(trait_item);
}
self.offset(-INDENT);
self.end();
self.word("}");
self.hardbreak();
}
fn item_trait_alias(&mut self, item: &ItemTraitAlias) {
self.outer_attrs(&item.attrs);
self.cbox(INDENT);
self.visibility(&item.vis);
self.word("trait ");
self.ident(&item.ident);
self.generics(&item.generics);
self.word(" = ");
self.neverbreak();
for bound in item.bounds.iter().delimited() {
if !bound.is_first {
self.space();
self.word("+ ");
}
self.type_param_bound(&bound);
}
self.where_clause_semi(&item.generics.where_clause);
self.end();
self.hardbreak();
}
fn item_type(&mut self, item: &ItemType) {
self.outer_attrs(&item.attrs);
self.cbox(INDENT);
self.visibility(&item.vis);
self.word("type ");
self.ident(&item.ident);
self.generics(&item.generics);
self.where_clause_oneline(&item.generics.where_clause);
self.word("= ");
self.neverbreak();
self.ibox(-INDENT);
self.ty(&item.ty);
self.end();
self.word(";");
self.end();
self.hardbreak();
}
fn item_union(&mut self, item: &ItemUnion) {
self.outer_attrs(&item.attrs);
self.cbox(INDENT);
self.visibility(&item.vis);
self.word("union ");
self.ident(&item.ident);
self.generics(&item.generics);
self.where_clause_for_body(&item.generics.where_clause);
self.word("{");
self.hardbreak_if_nonempty();
for field in &item.fields.named {
self.field(field);
self.word(",");
self.hardbreak();
}
self.offset(-INDENT);
self.end();
self.word("}");
self.hardbreak();
}
fn item_use(&mut self, item: &ItemUse) {
self.outer_attrs(&item.attrs);
self.visibility(&item.vis);
self.word("use ");
if item.leading_colon.is_some() {
self.word("::");
}
self.use_tree(&item.tree);
self.word(";");
self.hardbreak();
}
#[cfg(not(feature = "verbatim"))]
fn item_verbatim(&mut self, item: &TokenStream) {
if !item.is_empty() {
unimplemented!("Item::Verbatim `{}`", item);
}
self.hardbreak();
}
#[cfg(feature = "verbatim")]
fn item_verbatim(&mut self, tokens: &TokenStream) {
use syn::parse::{Parse, ParseStream, Result};
use syn::punctuated::Punctuated;
use syn::{
braced, parenthesized, token, Attribute, Generics, Ident, Lifetime, Token, Visibility,
};
use verbatim::{
FlexibleItemConst, FlexibleItemFn, FlexibleItemStatic, FlexibleItemType,
WhereClauseLocation,
};
enum ItemVerbatim {
Empty,
Ellipsis,
ConstFlexible(FlexibleItemConst),
FnFlexible(FlexibleItemFn),
ImplFlexible(ImplFlexible),
Macro2(Macro2),
StaticFlexible(FlexibleItemStatic),
TypeFlexible(FlexibleItemType),
UseBrace(UseBrace),
}
struct ImplFlexible {
attrs: Vec<Attribute>,
vis: Visibility,
defaultness: bool,
unsafety: bool,
generics: Generics,
constness: ImplConstness,
negative_impl: bool,
trait_: Option<Type>,
self_ty: Type,
items: Vec<ImplItem>,
}
enum ImplConstness {
None,
MaybeConst,
Const,
}
struct Macro2 {
attrs: Vec<Attribute>,
vis: Visibility,
ident: Ident,
args: Option<TokenStream>,
body: TokenStream,
}
struct UseBrace {
attrs: Vec<Attribute>,
vis: Visibility,
trees: Punctuated<RootUseTree, Token![,]>,
}
struct RootUseTree {
leading_colon: Option<Token![::]>,
inner: UseTree,
}
impl Parse for ImplConstness {
fn parse(input: ParseStream) -> Result<Self> {
if input.parse::<Option<Token![?]>>()?.is_some() {
input.parse::<Token![const]>()?;
Ok(ImplConstness::MaybeConst)
} else if input.parse::<Option<Token![const]>>()?.is_some() {
Ok(ImplConstness::Const)
} else {
Ok(ImplConstness::None)
}
}
}
impl Parse for RootUseTree {
fn parse(input: ParseStream) -> Result<Self> {
Ok(RootUseTree {
leading_colon: input.parse()?,
inner: input.parse()?,
})
}
}
impl Parse for ItemVerbatim {
fn parse(input: ParseStream) -> Result<Self> {
if input.is_empty() {
return Ok(ItemVerbatim::Empty);
} else if input.peek(Token![...]) {
input.parse::<Token![...]>()?;
return Ok(ItemVerbatim::Ellipsis);
}
let mut attrs = input.call(Attribute::parse_outer)?;
let vis: Visibility = input.parse()?;
let lookahead = input.lookahead1();
if lookahead.peek(Token![const]) && (input.peek2(Ident) || input.peek2(Token![_])) {
let defaultness = false;
let flexible_item = FlexibleItemConst::parse(attrs, vis, defaultness, input)?;
Ok(ItemVerbatim::ConstFlexible(flexible_item))
} else if input.peek(Token![const])
|| lookahead.peek(Token![async])
|| lookahead.peek(Token![unsafe]) && !input.peek2(Token![impl])
|| lookahead.peek(Token![extern])
|| lookahead.peek(Token![fn])
{
let defaultness = false;
let flexible_item = FlexibleItemFn::parse(attrs, vis, defaultness, input)?;
Ok(ItemVerbatim::FnFlexible(flexible_item))
} else if lookahead.peek(Token![default])
|| input.peek(Token![unsafe])
|| lookahead.peek(Token![impl])
{
let defaultness = input.parse::<Option<Token![default]>>()?.is_some();
let unsafety = input.parse::<Option<Token![unsafe]>>()?.is_some();
input.parse::<Token![impl]>()?;
let has_generics = input.peek(Token![<])
&& (input.peek2(Token![>])
|| input.peek2(Token![#])
|| (input.peek2(Ident) || input.peek2(Lifetime))
&& (input.peek3(Token![:])
|| input.peek3(Token![,])
|| input.peek3(Token![>])
|| input.peek3(Token![=]))
|| input.peek2(Token![const]));
let mut generics: Generics = if has_generics {
input.parse()?
} else {
Generics::default()
};
let constness: ImplConstness = input.parse()?;
let negative_impl =
!input.peek2(token::Brace) && input.parse::<Option<Token![!]>>()?.is_some();
let first_ty: Type = input.parse()?;
let (trait_, self_ty) = if input.parse::<Option<Token![for]>>()?.is_some() {
(Some(first_ty), input.parse()?)
} else {
(None, first_ty)
};
generics.where_clause = input.parse()?;
let content;
braced!(content in input);
let inner_attrs = content.call(Attribute::parse_inner)?;
attrs.extend(inner_attrs);
let mut items = Vec::new();
while !content.is_empty() {
items.push(content.parse()?);
}
Ok(ItemVerbatim::ImplFlexible(ImplFlexible {
attrs,
vis,
defaultness,
unsafety,
generics,
constness,
negative_impl,
trait_,
self_ty,
items,
}))
} else if lookahead.peek(Token![macro]) {
input.parse::<Token![macro]>()?;
let ident: Ident = input.parse()?;
let args = if input.peek(token::Paren) {
let paren_content;
parenthesized!(paren_content in input);
Some(paren_content.parse::<TokenStream>()?)
} else {
None
};
let brace_content;
braced!(brace_content in input);
let body: TokenStream = brace_content.parse()?;
Ok(ItemVerbatim::Macro2(Macro2 {
attrs,
vis,
ident,
args,
body,
}))
} else if lookahead.peek(Token![static]) {
let flexible_item = FlexibleItemStatic::parse(attrs, vis, input)?;
Ok(ItemVerbatim::StaticFlexible(flexible_item))
} else if lookahead.peek(Token![type]) {
let defaultness = false;
let flexible_item = FlexibleItemType::parse(
attrs,
vis,
defaultness,
input,
WhereClauseLocation::BeforeEq,
)?;
Ok(ItemVerbatim::TypeFlexible(flexible_item))
} else if lookahead.peek(Token![use]) {
input.parse::<Token![use]>()?;
let content;
braced!(content in input);
let trees = content.parse_terminated(RootUseTree::parse, Token![,])?;
input.parse::<Token![;]>()?;
Ok(ItemVerbatim::UseBrace(UseBrace { attrs, vis, trees }))
} else {
Err(lookahead.error())
}
}
}
let item: ItemVerbatim = match syn::parse2(tokens.clone()) {
Ok(item) => item,
Err(_) => unimplemented!("Item::Verbatim `{}`", tokens),
};
match item {
ItemVerbatim::Empty => {
self.hardbreak();
}
ItemVerbatim::Ellipsis => {
self.word("...");
self.hardbreak();
}
ItemVerbatim::ConstFlexible(item) => {
self.flexible_item_const(&item);
}
ItemVerbatim::FnFlexible(item) => {
self.flexible_item_fn(&item);
}
ItemVerbatim::ImplFlexible(item) => {
self.outer_attrs(&item.attrs);
self.cbox(INDENT);
self.ibox(-INDENT);
self.cbox(INDENT);
self.visibility(&item.vis);
if item.defaultness {
self.word("default ");
}
if item.unsafety {
self.word("unsafe ");
}
self.word("impl");
self.generics(&item.generics);
self.end();
self.nbsp();
match item.constness {
ImplConstness::None => {}
ImplConstness::MaybeConst => self.word("?const "),
ImplConstness::Const => self.word("const "),
}
if item.negative_impl {
self.word("!");
}
if let Some(trait_) = &item.trait_ {
self.ty(trait_);
self.space();
self.word("for ");
}
self.ty(&item.self_ty);
self.end();
self.where_clause_for_body(&item.generics.where_clause);
self.word("{");
self.hardbreak_if_nonempty();
self.inner_attrs(&item.attrs);
for impl_item in &item.items {
self.impl_item(impl_item);
}
self.offset(-INDENT);
self.end();
self.word("}");
self.hardbreak();
}
ItemVerbatim::Macro2(item) => {
self.outer_attrs(&item.attrs);
self.visibility(&item.vis);
self.word("macro ");
self.ident(&item.ident);
if let Some(args) = &item.args {
self.word("(");
self.cbox(INDENT);
self.zerobreak();
self.ibox(0);
self.macro_rules_tokens(args.clone(), true);
self.end();
self.zerobreak();
self.offset(-INDENT);
self.end();
self.word(")");
}
self.word(" {");
if !item.body.is_empty() {
self.neverbreak();
self.cbox(INDENT);
self.hardbreak();
self.ibox(0);
self.macro_rules_tokens(item.body.clone(), false);
self.end();
self.hardbreak();
self.offset(-INDENT);
self.end();
}
self.word("}");
self.hardbreak();
}
ItemVerbatim::StaticFlexible(item) => {
self.flexible_item_static(&item);
}
ItemVerbatim::TypeFlexible(item) => {
self.flexible_item_type(&item);
}
ItemVerbatim::UseBrace(item) => {
self.outer_attrs(&item.attrs);
self.visibility(&item.vis);
self.word("use ");
if item.trees.len() == 1 {
self.word("::");
self.use_tree(&item.trees[0].inner);
} else {
self.cbox(INDENT);
self.word("{");
self.zerobreak();
self.ibox(0);
for use_tree in item.trees.iter().delimited() {
if use_tree.leading_colon.is_some() {
self.word("::");
}
self.use_tree(&use_tree.inner);
if !use_tree.is_last {
self.word(",");
let mut use_tree = &use_tree.inner;
while let UseTree::Path(use_path) = use_tree {
use_tree = &use_path.tree;
}
if let UseTree::Group(_) = use_tree {
self.hardbreak();
} else {
self.space();
}
}
}
self.end();
self.trailing_comma(true);
self.offset(-INDENT);
self.word("}");
self.end();
}
self.word(";");
self.hardbreak();
}
}
}
fn use_tree(&mut self, use_tree: &UseTree) {
match use_tree {
UseTree::Path(use_path) => self.use_path(use_path),
UseTree::Name(use_name) => self.use_name(use_name),
UseTree::Rename(use_rename) => self.use_rename(use_rename),
UseTree::Glob(use_glob) => self.use_glob(use_glob),
UseTree::Group(use_group) => self.use_group(use_group),
}
}
fn use_path(&mut self, use_path: &UsePath) {
self.ident(&use_path.ident);
self.word("::");
self.use_tree(&use_path.tree);
}
fn use_name(&mut self, use_name: &UseName) {
self.ident(&use_name.ident);
}
fn use_rename(&mut self, use_rename: &UseRename) {
self.ident(&use_rename.ident);
self.word(" as ");
self.ident(&use_rename.rename);
}
fn use_glob(&mut self, use_glob: &UseGlob) {
let _ = use_glob;
self.word("*");
}
fn use_group(&mut self, use_group: &UseGroup) {
if use_group.items.is_empty() {
self.word("{}");
} else if use_group.items.len() == 1
&& match &use_group.items[0] {
UseTree::Rename(use_rename) => use_rename.ident != "self",
_ => true,
}
{
self.use_tree(&use_group.items[0]);
} else {
self.cbox(INDENT);
self.word("{");
self.zerobreak();
self.ibox(0);
for use_tree in use_group.items.iter().delimited() {
self.use_tree(&use_tree);
if !use_tree.is_last {
self.word(",");
let mut use_tree = *use_tree;
while let UseTree::Path(use_path) = use_tree {
use_tree = &use_path.tree;
}
if let UseTree::Group(_) = use_tree {
self.hardbreak();
} else {
self.space();
}
}
}
self.end();
self.trailing_comma(true);
self.offset(-INDENT);
self.word("}");
self.end();
}
}
fn foreign_item(&mut self, foreign_item: &ForeignItem) {
match foreign_item {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
ForeignItem::Fn(item) => self.foreign_item_fn(item),
ForeignItem::Static(item) => self.foreign_item_static(item),
ForeignItem::Type(item) => self.foreign_item_type(item),
ForeignItem::Macro(item) => self.foreign_item_macro(item),
ForeignItem::Verbatim(item) => self.foreign_item_verbatim(item),
_ => unimplemented!("unknown ForeignItem"),
}
}
fn foreign_item_fn(&mut self, foreign_item: &ForeignItemFn) {
self.outer_attrs(&foreign_item.attrs);
self.cbox(INDENT);
self.visibility(&foreign_item.vis);
self.signature(&foreign_item.sig);
self.where_clause_semi(&foreign_item.sig.generics.where_clause);
self.end();
self.hardbreak();
}
fn foreign_item_static(&mut self, foreign_item: &ForeignItemStatic) {
self.outer_attrs(&foreign_item.attrs);
self.cbox(0);
self.visibility(&foreign_item.vis);
self.word("static ");
self.static_mutability(&foreign_item.mutability);
self.ident(&foreign_item.ident);
self.word(": ");
self.ty(&foreign_item.ty);
self.word(";");
self.end();
self.hardbreak();
}
fn foreign_item_type(&mut self, foreign_item: &ForeignItemType) {
self.outer_attrs(&foreign_item.attrs);
self.cbox(0);
self.visibility(&foreign_item.vis);
self.word("type ");
self.ident(&foreign_item.ident);
self.generics(&foreign_item.generics);
self.word(";");
self.end();
self.hardbreak();
}
fn foreign_item_macro(&mut self, foreign_item: &ForeignItemMacro) {
self.outer_attrs(&foreign_item.attrs);
let semicolon = true;
self.mac(&foreign_item.mac, None, semicolon);
self.hardbreak();
}
#[cfg(not(feature = "verbatim"))]
fn foreign_item_verbatim(&mut self, foreign_item: &TokenStream) {
if !foreign_item.is_empty() {
unimplemented!("ForeignItem::Verbatim `{}`", foreign_item);
}
self.hardbreak();
}
#[cfg(feature = "verbatim")]
fn foreign_item_verbatim(&mut self, tokens: &TokenStream) {
use syn::parse::{Parse, ParseStream, Result};
use syn::{Attribute, Token, Visibility};
use verbatim::{FlexibleItemFn, FlexibleItemStatic, FlexibleItemType, WhereClauseLocation};
enum ForeignItemVerbatim {
Empty,
Ellipsis,
FnFlexible(FlexibleItemFn),
StaticFlexible(FlexibleItemStatic),
TypeFlexible(FlexibleItemType),
}
impl Parse for ForeignItemVerbatim {
fn parse(input: ParseStream) -> Result<Self> {
if input.is_empty() {
return Ok(ForeignItemVerbatim::Empty);
} else if input.peek(Token![...]) {
input.parse::<Token![...]>()?;
return Ok(ForeignItemVerbatim::Ellipsis);
}
let attrs = input.call(Attribute::parse_outer)?;
let vis: Visibility = input.parse()?;
let defaultness = false;
let lookahead = input.lookahead1();
if lookahead.peek(Token![const])
|| lookahead.peek(Token![async])
|| lookahead.peek(Token![unsafe])
|| lookahead.peek(Token![extern])
|| lookahead.peek(Token![fn])
{
let flexible_item = FlexibleItemFn::parse(attrs, vis, defaultness, input)?;
Ok(ForeignItemVerbatim::FnFlexible(flexible_item))
} else if lookahead.peek(Token![static]) {
let flexible_item = FlexibleItemStatic::parse(attrs, vis, input)?;
Ok(ForeignItemVerbatim::StaticFlexible(flexible_item))
} else if lookahead.peek(Token![type]) {
let flexible_item = FlexibleItemType::parse(
attrs,
vis,
defaultness,
input,
WhereClauseLocation::Both,
)?;
Ok(ForeignItemVerbatim::TypeFlexible(flexible_item))
} else {
Err(lookahead.error())
}
}
}
let foreign_item: ForeignItemVerbatim = match syn::parse2(tokens.clone()) {
Ok(foreign_item) => foreign_item,
Err(_) => unimplemented!("ForeignItem::Verbatim `{}`", tokens),
};
match foreign_item {
ForeignItemVerbatim::Empty => {
self.hardbreak();
}
ForeignItemVerbatim::Ellipsis => {
self.word("...");
self.hardbreak();
}
ForeignItemVerbatim::FnFlexible(foreign_item) => {
self.flexible_item_fn(&foreign_item);
}
ForeignItemVerbatim::StaticFlexible(foreign_item) => {
self.flexible_item_static(&foreign_item);
}
ForeignItemVerbatim::TypeFlexible(foreign_item) => {
self.flexible_item_type(&foreign_item);
}
}
}
fn trait_item(&mut self, trait_item: &TraitItem) {
match trait_item {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
TraitItem::Const(item) => self.trait_item_const(item),
TraitItem::Fn(item) => self.trait_item_fn(item),
TraitItem::Type(item) => self.trait_item_type(item),
TraitItem::Macro(item) => self.trait_item_macro(item),
TraitItem::Verbatim(item) => self.trait_item_verbatim(item),
_ => unimplemented!("unknown TraitItem"),
}
}
fn trait_item_const(&mut self, trait_item: &TraitItemConst) {
self.outer_attrs(&trait_item.attrs);
self.cbox(0);
self.word("const ");
self.ident(&trait_item.ident);
self.generics(&trait_item.generics);
self.word(": ");
self.ty(&trait_item.ty);
if let Some((_eq_token, default)) = &trait_item.default {
self.word(" = ");
self.neverbreak();
self.expr(default);
}
self.word(";");
self.end();
self.hardbreak();
}
fn trait_item_fn(&mut self, trait_item: &TraitItemFn) {
self.outer_attrs(&trait_item.attrs);
self.cbox(INDENT);
self.signature(&trait_item.sig);
if let Some(block) = &trait_item.default {
self.where_clause_for_body(&trait_item.sig.generics.where_clause);
self.word("{");
self.hardbreak_if_nonempty();
self.inner_attrs(&trait_item.attrs);
for stmt in &block.stmts {
self.stmt(stmt);
}
self.offset(-INDENT);
self.end();
self.word("}");
} else {
self.where_clause_semi(&trait_item.sig.generics.where_clause);
self.end();
}
self.hardbreak();
}
fn trait_item_type(&mut self, trait_item: &TraitItemType) {
self.outer_attrs(&trait_item.attrs);
self.cbox(INDENT);
self.word("type ");
self.ident(&trait_item.ident);
self.generics(&trait_item.generics);
for bound in trait_item.bounds.iter().delimited() {
if bound.is_first {
self.word(": ");
} else {
self.space();
self.word("+ ");
}
self.type_param_bound(&bound);
}
if let Some((_eq_token, default)) = &trait_item.default {
self.word(" = ");
self.neverbreak();
self.ibox(-INDENT);
self.ty(default);
self.end();
}
self.where_clause_oneline_semi(&trait_item.generics.where_clause);
self.end();
self.hardbreak();
}
fn trait_item_macro(&mut self, trait_item: &TraitItemMacro) {
self.outer_attrs(&trait_item.attrs);
let semicolon = true;
self.mac(&trait_item.mac, None, semicolon);
self.hardbreak();
}
#[cfg(not(feature = "verbatim"))]
fn trait_item_verbatim(&mut self, trait_item: &TokenStream) {
if !trait_item.is_empty() {
unimplemented!("TraitItem::Verbatim `{}`", trait_item);
}
self.hardbreak();
}
#[cfg(feature = "verbatim")]
fn trait_item_verbatim(&mut self, tokens: &TokenStream) {
use syn::parse::{Parse, ParseStream, Result};
use syn::{Attribute, Ident, Token, Visibility};
use verbatim::{FlexibleItemConst, FlexibleItemType, WhereClauseLocation};
enum TraitItemVerbatim {
Empty,
Ellipsis,
ConstFlexible(FlexibleItemConst),
TypeFlexible(FlexibleItemType),
PubOrDefault(PubOrDefaultTraitItem),
}
struct PubOrDefaultTraitItem {
attrs: Vec<Attribute>,
vis: Visibility,
defaultness: bool,
trait_item: TraitItem,
}
impl Parse for TraitItemVerbatim {
fn parse(input: ParseStream) -> Result<Self> {
if input.is_empty() {
return Ok(TraitItemVerbatim::Empty);
} else if input.peek(Token![...]) {
input.parse::<Token![...]>()?;
return Ok(TraitItemVerbatim::Ellipsis);
}
let attrs = input.call(Attribute::parse_outer)?;
let vis: Visibility = input.parse()?;
let defaultness = input.parse::<Option<Token![default]>>()?.is_some();
let lookahead = input.lookahead1();
if lookahead.peek(Token![const]) && (input.peek2(Ident) || input.peek2(Token![_])) {
let flexible_item = FlexibleItemConst::parse(attrs, vis, defaultness, input)?;
Ok(TraitItemVerbatim::ConstFlexible(flexible_item))
} else if lookahead.peek(Token![type]) {
let flexible_item = FlexibleItemType::parse(
attrs,
vis,
defaultness,
input,
WhereClauseLocation::AfterEq,
)?;
Ok(TraitItemVerbatim::TypeFlexible(flexible_item))
} else if (input.peek(Token![const])
|| lookahead.peek(Token![async])
|| lookahead.peek(Token![unsafe])
|| lookahead.peek(Token![extern])
|| lookahead.peek(Token![fn]))
&& (!matches!(vis, Visibility::Inherited) || defaultness)
{
Ok(TraitItemVerbatim::PubOrDefault(PubOrDefaultTraitItem {
attrs,
vis,
defaultness,
trait_item: input.parse()?,
}))
} else {
Err(lookahead.error())
}
}
}
let impl_item: TraitItemVerbatim = match syn::parse2(tokens.clone()) {
Ok(impl_item) => impl_item,
Err(_) => unimplemented!("TraitItem::Verbatim `{}`", tokens),
};
match impl_item {
TraitItemVerbatim::Empty => {
self.hardbreak();
}
TraitItemVerbatim::Ellipsis => {
self.word("...");
self.hardbreak();
}
TraitItemVerbatim::ConstFlexible(trait_item) => {
self.flexible_item_const(&trait_item);
}
TraitItemVerbatim::TypeFlexible(trait_item) => {
self.flexible_item_type(&trait_item);
}
TraitItemVerbatim::PubOrDefault(trait_item) => {
self.outer_attrs(&trait_item.attrs);
self.visibility(&trait_item.vis);
if trait_item.defaultness {
self.word("default ");
}
self.trait_item(&trait_item.trait_item);
}
}
}
fn impl_item(&mut self, impl_item: &ImplItem) {
match impl_item {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
ImplItem::Const(item) => self.impl_item_const(item),
ImplItem::Fn(item) => self.impl_item_fn(item),
ImplItem::Type(item) => self.impl_item_type(item),
ImplItem::Macro(item) => self.impl_item_macro(item),
ImplItem::Verbatim(item) => self.impl_item_verbatim(item),
_ => unimplemented!("unknown ImplItem"),
}
}
fn impl_item_const(&mut self, impl_item: &ImplItemConst) {
self.outer_attrs(&impl_item.attrs);
self.cbox(0);
self.visibility(&impl_item.vis);
if impl_item.defaultness.is_some() {
self.word("default ");
}
self.word("const ");
self.ident(&impl_item.ident);
self.generics(&impl_item.generics);
self.word(": ");
self.ty(&impl_item.ty);
self.word(" = ");
self.neverbreak();
self.expr(&impl_item.expr);
self.word(";");
self.end();
self.hardbreak();
}
fn impl_item_fn(&mut self, impl_item: &ImplItemFn) {
self.outer_attrs(&impl_item.attrs);
self.cbox(INDENT);
self.visibility(&impl_item.vis);
if impl_item.defaultness.is_some() {
self.word("default ");
}
self.signature(&impl_item.sig);
self.where_clause_for_body(&impl_item.sig.generics.where_clause);
self.word("{");
self.hardbreak_if_nonempty();
self.inner_attrs(&impl_item.attrs);
for stmt in &impl_item.block.stmts {
self.stmt(stmt);
}
self.offset(-INDENT);
self.end();
self.word("}");
self.hardbreak();
}
fn impl_item_type(&mut self, impl_item: &ImplItemType) {
self.outer_attrs(&impl_item.attrs);
self.cbox(INDENT);
self.visibility(&impl_item.vis);
if impl_item.defaultness.is_some() {
self.word("default ");
}
self.word("type ");
self.ident(&impl_item.ident);
self.generics(&impl_item.generics);
self.word(" = ");
self.neverbreak();
self.ibox(-INDENT);
self.ty(&impl_item.ty);
self.end();
self.where_clause_oneline_semi(&impl_item.generics.where_clause);
self.end();
self.hardbreak();
}
fn impl_item_macro(&mut self, impl_item: &ImplItemMacro) {
self.outer_attrs(&impl_item.attrs);
let semicolon = true;
self.mac(&impl_item.mac, None, semicolon);
self.hardbreak();
}
#[cfg(not(feature = "verbatim"))]
fn impl_item_verbatim(&mut self, impl_item: &TokenStream) {
if !impl_item.is_empty() {
unimplemented!("ImplItem::Verbatim `{}`", impl_item);
}
self.hardbreak();
}
#[cfg(feature = "verbatim")]
fn impl_item_verbatim(&mut self, tokens: &TokenStream) {
use syn::parse::{Parse, ParseStream, Result};
use syn::{Attribute, Ident, Token, Visibility};
use verbatim::{FlexibleItemConst, FlexibleItemFn, FlexibleItemType, WhereClauseLocation};
enum ImplItemVerbatim {
Empty,
Ellipsis,
ConstFlexible(FlexibleItemConst),
FnFlexible(FlexibleItemFn),
TypeFlexible(FlexibleItemType),
}
impl Parse for ImplItemVerbatim {
fn parse(input: ParseStream) -> Result<Self> {
if input.is_empty() {
return Ok(ImplItemVerbatim::Empty);
} else if input.peek(Token![...]) {
input.parse::<Token![...]>()?;
return Ok(ImplItemVerbatim::Ellipsis);
}
let attrs = input.call(Attribute::parse_outer)?;
let vis: Visibility = input.parse()?;
let defaultness = input.parse::<Option<Token![default]>>()?.is_some();
let lookahead = input.lookahead1();
if lookahead.peek(Token![const]) && (input.peek2(Ident) || input.peek2(Token![_])) {
let flexible_item = FlexibleItemConst::parse(attrs, vis, defaultness, input)?;
Ok(ImplItemVerbatim::ConstFlexible(flexible_item))
} else if input.peek(Token![const])
|| lookahead.peek(Token![async])
|| lookahead.peek(Token![unsafe])
|| lookahead.peek(Token![extern])
|| lookahead.peek(Token![fn])
{
let flexible_item = FlexibleItemFn::parse(attrs, vis, defaultness, input)?;
Ok(ImplItemVerbatim::FnFlexible(flexible_item))
} else if lookahead.peek(Token![type]) {
let flexible_item = FlexibleItemType::parse(
attrs,
vis,
defaultness,
input,
WhereClauseLocation::AfterEq,
)?;
Ok(ImplItemVerbatim::TypeFlexible(flexible_item))
} else {
Err(lookahead.error())
}
}
}
let impl_item: ImplItemVerbatim = match syn::parse2(tokens.clone()) {
Ok(impl_item) => impl_item,
Err(_) => unimplemented!("ImplItem::Verbatim `{}`", tokens),
};
match impl_item {
ImplItemVerbatim::Empty => {
self.hardbreak();
}
ImplItemVerbatim::Ellipsis => {
self.word("...");
self.hardbreak();
}
ImplItemVerbatim::ConstFlexible(impl_item) => {
self.flexible_item_const(&impl_item);
}
ImplItemVerbatim::FnFlexible(impl_item) => {
self.flexible_item_fn(&impl_item);
}
ImplItemVerbatim::TypeFlexible(impl_item) => {
self.flexible_item_type(&impl_item);
}
}
}
fn signature(&mut self, signature: &Signature) {
if signature.constness.is_some() {
self.word("const ");
}
if signature.asyncness.is_some() {
self.word("async ");
}
if signature.unsafety.is_some() {
self.word("unsafe ");
}
if let Some(abi) = &signature.abi {
self.abi(abi);
}
self.word("fn ");
self.ident(&signature.ident);
self.generics(&signature.generics);
self.word("(");
self.neverbreak();
self.cbox(0);
self.zerobreak();
for input in signature.inputs.iter().delimited() {
self.fn_arg(&input);
let is_last = input.is_last && signature.variadic.is_none();
self.trailing_comma(is_last);
}
if let Some(variadic) = &signature.variadic {
self.variadic(variadic);
self.zerobreak();
}
self.offset(-INDENT);
self.end();
self.word(")");
self.cbox(-INDENT);
self.return_type(&signature.output);
self.end();
}
fn fn_arg(&mut self, fn_arg: &FnArg) {
match fn_arg {
FnArg::Receiver(receiver) => self.receiver(receiver),
FnArg::Typed(pat_type) => self.pat_type(pat_type),
}
}
fn receiver(&mut self, receiver: &Receiver) {
self.outer_attrs(&receiver.attrs);
if let Some((_ampersand, lifetime)) = &receiver.reference {
self.word("&");
if let Some(lifetime) = lifetime {
self.lifetime(lifetime);
self.nbsp();
}
}
if receiver.mutability.is_some() {
self.word("mut ");
}
self.word("self");
if receiver.colon_token.is_some() {
self.word(": ");
self.ty(&receiver.ty);
} else {
let consistent = match (&receiver.reference, &receiver.mutability, &*receiver.ty) {
(Some(_), mutability, Type::Reference(ty)) => {
mutability.is_some() == ty.mutability.is_some()
&& match &*ty.elem {
Type::Path(ty) => ty.qself.is_none() && ty.path.is_ident("Self"),
_ => false,
}
}
(None, _, Type::Path(ty)) => ty.qself.is_none() && ty.path.is_ident("Self"),
_ => false,
};
if !consistent {
self.word(": ");
self.ty(&receiver.ty);
}
}
}
fn variadic(&mut self, variadic: &Variadic) {
self.outer_attrs(&variadic.attrs);
if let Some((pat, _colon)) = &variadic.pat {
self.pat(pat);
self.word(": ");
}
self.word("...");
}
fn static_mutability(&mut self, mutability: &StaticMutability) {
match mutability {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
StaticMutability::Mut(_) => self.word("mut "),
StaticMutability::None => {}
_ => unimplemented!("unknown StaticMutability"),
}
}
}
#[cfg(feature = "verbatim")]
mod verbatim {
use crate::algorithm::Printer;
use crate::iter::IterDelimited;
use crate::INDENT;
use syn::ext::IdentExt;
use syn::parse::{ParseStream, Result};
use syn::{
braced, token, Attribute, Block, Expr, Generics, Ident, Signature, StaticMutability, Stmt,
Token, Type, TypeParamBound, Visibility, WhereClause,
};
pub struct FlexibleItemConst {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub defaultness: bool,
pub ident: Ident,
pub generics: Generics,
pub ty: Type,
pub value: Option<Expr>,
}
pub struct FlexibleItemFn {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub defaultness: bool,
pub sig: Signature,
pub body: Option<Vec<Stmt>>,
}
pub struct FlexibleItemStatic {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub mutability: StaticMutability,
pub ident: Ident,
pub ty: Option<Type>,
pub expr: Option<Expr>,
}
pub struct FlexibleItemType {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub defaultness: bool,
pub ident: Ident,
pub generics: Generics,
pub bounds: Vec<TypeParamBound>,
pub definition: Option<Type>,
pub where_clause_after_eq: Option<WhereClause>,
}
pub enum WhereClauseLocation {
BeforeEq,
AfterEq,
Both,
}
impl FlexibleItemConst {
pub fn parse(
attrs: Vec<Attribute>,
vis: Visibility,
defaultness: bool,
input: ParseStream,
) -> Result<Self> {
input.parse::<Token![const]>()?;
let ident = input.call(Ident::parse_any)?;
let mut generics: Generics = input.parse()?;
input.parse::<Token![:]>()?;
let ty: Type = input.parse()?;
let value = if input.parse::<Option<Token![=]>>()?.is_some() {
let expr: Expr = input.parse()?;
Some(expr)
} else {
None
};
generics.where_clause = input.parse()?;
input.parse::<Token![;]>()?;
Ok(FlexibleItemConst {
attrs,
vis,
defaultness,
ident,
generics,
ty,
value,
})
}
}
impl FlexibleItemFn {
pub fn parse(
mut attrs: Vec<Attribute>,
vis: Visibility,
defaultness: bool,
input: ParseStream,
) -> Result<Self> {
let sig: Signature = input.parse()?;
let lookahead = input.lookahead1();
let body = if lookahead.peek(Token![;]) {
input.parse::<Token![;]>()?;
None
} else if lookahead.peek(token::Brace) {
let content;
braced!(content in input);
attrs.extend(content.call(Attribute::parse_inner)?);
Some(content.call(Block::parse_within)?)
} else {
return Err(lookahead.error());
};
Ok(FlexibleItemFn {
attrs,
vis,
defaultness,
sig,
body,
})
}
}
impl FlexibleItemStatic {
pub fn parse(attrs: Vec<Attribute>, vis: Visibility, input: ParseStream) -> Result<Self> {
input.parse::<Token![static]>()?;
let mutability: StaticMutability = input.parse()?;
let ident = input.parse()?;
let lookahead = input.lookahead1();
let has_type = lookahead.peek(Token![:]);
let has_expr = lookahead.peek(Token![=]);
if !has_type && !has_expr {
return Err(lookahead.error());
}
let ty: Option<Type> = if has_type {
input.parse::<Token![:]>()?;
input.parse().map(Some)?
} else {
None
};
let expr: Option<Expr> = if input.parse::<Option<Token![=]>>()?.is_some() {
input.parse().map(Some)?
} else {
None
};
input.parse::<Token![;]>()?;
Ok(FlexibleItemStatic {
attrs,
vis,
mutability,
ident,
ty,
expr,
})
}
}
impl FlexibleItemType {
pub fn parse(
attrs: Vec<Attribute>,
vis: Visibility,
defaultness: bool,
input: ParseStream,
where_clause_location: WhereClauseLocation,
) -> Result<Self> {
input.parse::<Token![type]>()?;
let ident: Ident = input.parse()?;
let mut generics: Generics = input.parse()?;
let mut bounds = Vec::new();
if input.parse::<Option<Token![:]>>()?.is_some() {
loop {
if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) {
break;
}
bounds.push(input.parse::<TypeParamBound>()?);
if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) {
break;
}
input.parse::<Token![+]>()?;
}
}
match where_clause_location {
WhereClauseLocation::BeforeEq | WhereClauseLocation::Both => {
generics.where_clause = input.parse()?;
}
WhereClauseLocation::AfterEq => {}
}
let definition = if input.parse::<Option<Token![=]>>()?.is_some() {
Some(input.parse()?)
} else {
None
};
let where_clause_after_eq = match where_clause_location {
WhereClauseLocation::AfterEq | WhereClauseLocation::Both
if generics.where_clause.is_none() =>
{
input.parse()?
}
_ => None,
};
input.parse::<Token![;]>()?;
Ok(FlexibleItemType {
attrs,
vis,
defaultness,
ident,
generics,
bounds,
definition,
where_clause_after_eq,
})
}
}
impl Printer {
pub fn flexible_item_const(&mut self, item: &FlexibleItemConst) {
self.outer_attrs(&item.attrs);
self.cbox(INDENT);
self.visibility(&item.vis);
if item.defaultness {
self.word("default ");
}
self.word("const ");
self.ident(&item.ident);
self.generics(&item.generics);
self.word(": ");
self.cbox(-INDENT);
self.ty(&item.ty);
self.end();
if let Some(value) = &item.value {
self.word(" = ");
self.neverbreak();
self.ibox(-INDENT);
self.expr(value);
self.end();
}
self.where_clause_oneline_semi(&item.generics.where_clause);
self.end();
self.hardbreak();
}
pub fn flexible_item_fn(&mut self, item: &FlexibleItemFn) {
self.outer_attrs(&item.attrs);
self.cbox(INDENT);
self.visibility(&item.vis);
if item.defaultness {
self.word("default ");
}
self.signature(&item.sig);
if let Some(body) = &item.body {
self.where_clause_for_body(&item.sig.generics.where_clause);
self.word("{");
self.hardbreak_if_nonempty();
self.inner_attrs(&item.attrs);
for stmt in body {
self.stmt(stmt);
}
self.offset(-INDENT);
self.end();
self.word("}");
} else {
self.where_clause_semi(&item.sig.generics.where_clause);
self.end();
}
self.hardbreak();
}
pub fn flexible_item_static(&mut self, item: &FlexibleItemStatic) {
self.outer_attrs(&item.attrs);
self.cbox(0);
self.visibility(&item.vis);
self.word("static ");
self.static_mutability(&item.mutability);
self.ident(&item.ident);
if let Some(ty) = &item.ty {
self.word(": ");
self.ty(ty);
}
if let Some(expr) = &item.expr {
self.word(" = ");
self.neverbreak();
self.expr(expr);
}
self.word(";");
self.end();
self.hardbreak();
}
pub fn flexible_item_type(&mut self, item: &FlexibleItemType) {
self.outer_attrs(&item.attrs);
self.cbox(INDENT);
self.visibility(&item.vis);
if item.defaultness {
self.word("default ");
}
self.word("type ");
self.ident(&item.ident);
self.generics(&item.generics);
for bound in item.bounds.iter().delimited() {
if bound.is_first {
self.word(": ");
} else {
self.space();
self.word("+ ");
}
self.type_param_bound(&bound);
}
if let Some(definition) = &item.definition {
self.where_clause_oneline(&item.generics.where_clause);
self.word("= ");
self.neverbreak();
self.ibox(-INDENT);
self.ty(definition);
self.end();
self.where_clause_oneline_semi(&item.where_clause_after_eq);
} else {
self.where_clause_oneline_semi(&item.generics.where_clause);
}
self.end();
self.hardbreak();
}
}
}