| 1 | |
| 2 |
|
| 3 | #[cfg(feature = "full")]
|
| 4 | use crate::expr::Expr;
|
| 5 | #[cfg(any(feature = "printing", feature = "full"))]
|
| 6 | use crate::generics::TypeParamBound;
|
| 7 | #[cfg(any(feature = "printing", feature = "full"))]
|
| 8 | use crate::path::{Path, PathArguments};
|
| 9 | #[cfg(any(feature = "printing", feature = "full"))]
|
| 10 | use crate::punctuated::Punctuated;
|
| 11 | #[cfg(any(feature = "printing", feature = "full"))]
|
| 12 | use crate::ty::{ReturnType, Type};
|
| 13 | #[cfg(feature = "full")]
|
| 14 | use proc_macro2::{Delimiter, TokenStream, TokenTree};
|
| 15 | #[cfg(any(feature = "printing", feature = "full"))]
|
| 16 | use std::ops::ControlFlow;
|
| 17 |
|
| 18 | #[cfg(feature = "full")]
|
| 19 | pub(crate) fn requires_semi_to_be_stmt(expr: &Expr) -> bool {
|
| 20 | match expr {
|
| 21 | Expr::Macro(expr) => !expr.mac.delimiter.is_brace(),
|
| 22 | _ => requires_comma_to_be_match_arm(expr),
|
| 23 | }
|
| 24 | }
|
| 25 |
|
| 26 | #[cfg(feature = "full")]
|
| 27 | pub(crate) fn requires_comma_to_be_match_arm(expr: &Expr) -> bool {
|
| 28 | match expr {
|
| 29 | Expr::If(_)
|
| 30 | | Expr::Match(_)
|
| 31 | | Expr::Block(_) | Expr::Unsafe(_) |
| 32 | | Expr::While(_)
|
| 33 | | Expr::Loop(_)
|
| 34 | | Expr::ForLoop(_)
|
| 35 | | Expr::TryBlock(_)
|
| 36 | | Expr::Const(_) => false,
|
| 37 |
|
| 38 | Expr::Array(_)
|
| 39 | | Expr::Assign(_)
|
| 40 | | Expr::Async(_)
|
| 41 | | Expr::Await(_)
|
| 42 | | Expr::Binary(_)
|
| 43 | | Expr::Break(_)
|
| 44 | | Expr::Call(_)
|
| 45 | | Expr::Cast(_)
|
| 46 | | Expr::Closure(_)
|
| 47 | | Expr::Continue(_)
|
| 48 | | Expr::Field(_)
|
| 49 | | Expr::Group(_)
|
| 50 | | Expr::Index(_)
|
| 51 | | Expr::Infer(_)
|
| 52 | | Expr::Let(_)
|
| 53 | | Expr::Lit(_)
|
| 54 | | Expr::Macro(_)
|
| 55 | | Expr::MethodCall(_)
|
| 56 | | Expr::Paren(_)
|
| 57 | | Expr::Path(_)
|
| 58 | | Expr::Range(_)
|
| 59 | | Expr::RawAddr(_)
|
| 60 | | Expr::Reference(_)
|
| 61 | | Expr::Repeat(_)
|
| 62 | | Expr::Return(_)
|
| 63 | | Expr::Struct(_)
|
| 64 | | Expr::Try(_)
|
| 65 | | Expr::Tuple(_)
|
| 66 | | Expr::Unary(_)
|
| 67 | | Expr::Yield(_)
|
| 68 | | Expr::Verbatim(_) => true,
|
| 69 | }
|
| 70 | }
|
| 71 |
|
| 72 | #[cfg(feature = "printing")]
|
| 73 | pub(crate) fn trailing_unparameterized_path(mut ty: &Type) -> bool {
|
| 74 | loop {
|
| 75 | match ty {
|
| 76 | Type::BareFn(t) => match &t.output {
|
| 77 | ReturnType::Default => return false,
|
| 78 | ReturnType::Type(_, ret) => ty = ret,
|
| 79 | },
|
| 80 | Type::ImplTrait(t) => match last_type_in_bounds(&t.bounds) {
|
| 81 | ControlFlow::Break(trailing_path) => return trailing_path,
|
| 82 | ControlFlow::Continue(t) => ty = t,
|
| 83 | },
|
| 84 | Type::Path(t) => match last_type_in_path(&t.path) {
|
| 85 | ControlFlow::Break(trailing_path) => return trailing_path,
|
| 86 | ControlFlow::Continue(t) => ty = t,
|
| 87 | },
|
| 88 | Type::Ptr(t) => ty = &t.elem,
|
| 89 | Type::Reference(t) => ty = &t.elem,
|
| 90 | Type::TraitObject(t) => match last_type_in_bounds(&t.bounds) {
|
| 91 | ControlFlow::Break(trailing_path) => return trailing_path,
|
| 92 | ControlFlow::Continue(t) => ty = t,
|
| 93 | },
|
| 94 |
|
| 95 | Type::Array(_)
|
| 96 | | Type::Group(_)
|
| 97 | | Type::Infer(_)
|
| 98 | | Type::Macro(_)
|
| 99 | | Type::Never(_)
|
| 100 | | Type::Paren(_)
|
| 101 | | Type::Slice(_)
|
| 102 | | Type::Tuple(_)
|
| 103 | | Type::Verbatim(_) => return false,
|
| 104 | }
|
| 105 | }
|
| 106 |
|
| 107 | fn last_type_in_path(path: &Path) -> ControlFlow<bool, &Type> {
|
| 108 | match &path.segments.last().unwrap().arguments {
|
| 109 | PathArguments::None => ControlFlow::Break(true),
|
| 110 | PathArguments::AngleBracketed(_) => ControlFlow::Break(false),
|
| 111 | PathArguments::Parenthesized(arg) => match &arg.output {
|
| 112 | ReturnType::Default => ControlFlow::Break(false),
|
| 113 | ReturnType::Type(_, ret) => ControlFlow::Continue(ret),
|
| 114 | },
|
| 115 | }
|
| 116 | }
|
| 117 |
|
| 118 | fn last_type_in_bounds(
|
| 119 | bounds: &Punctuated<TypeParamBound, Token![+]>,
|
| 120 | ) -> ControlFlow<bool, &Type> {
|
| 121 | match bounds.last().unwrap() {
|
| 122 | TypeParamBound::Trait(t) => last_type_in_path(&t.path),
|
| 123 | TypeParamBound::Lifetime(_)
|
| 124 | | TypeParamBound::PreciseCapture(_)
|
| 125 | | TypeParamBound::Verbatim(_) => ControlFlow::Break(false),
|
| 126 | }
|
| 127 | }
|
| 128 | }
|
| 129 |
|
| 130 | |
| 131 | #[cfg(all(feature = "printing", feature = "full"))]
|
| 132 | pub(crate) fn expr_leading_label(mut expr: &Expr) -> bool {
|
| 133 | loop {
|
| 134 | match expr {
|
| 135 | Expr::Block(e) => return e.label.is_some(),
|
| 136 | Expr::ForLoop(e) => return e.label.is_some(),
|
| 137 | Expr::Loop(e) => return e.label.is_some(),
|
| 138 | Expr::While(e) => return e.label.is_some(),
|
| 139 |
|
| 140 | Expr::Assign(e) => expr = &e.left,
|
| 141 | Expr::Await(e) => expr = &e.base,
|
| 142 | Expr::Binary(e) => expr = &e.left,
|
| 143 | Expr::Call(e) => expr = &e.func,
|
| 144 | Expr::Cast(e) => expr = &e.expr,
|
| 145 | Expr::Field(e) => expr = &e.base,
|
| 146 | Expr::Index(e) => expr = &e.expr,
|
| 147 | Expr::MethodCall(e) => expr = &e.receiver,
|
| 148 | Expr::Range(e) => match &e.start {
|
| 149 | Some(start) => expr = start,
|
| 150 | None => return false,
|
| 151 | },
|
| 152 | Expr::Try(e) => expr = &e.expr,
|
| 153 |
|
| 154 | Expr::Array(_)
|
| 155 | | Expr::Async(_)
|
| 156 | | Expr::Break(_)
|
| 157 | | Expr::Closure(_)
|
| 158 | | Expr::Const(_)
|
| 159 | | Expr::Continue(_)
|
| 160 | | Expr::Group(_)
|
| 161 | | Expr::If(_)
|
| 162 | | Expr::Infer(_)
|
| 163 | | Expr::Let(_)
|
| 164 | | Expr::Lit(_)
|
| 165 | | Expr::Macro(_)
|
| 166 | | Expr::Match(_)
|
| 167 | | Expr::Paren(_)
|
| 168 | | Expr::Path(_)
|
| 169 | | Expr::RawAddr(_)
|
| 170 | | Expr::Reference(_)
|
| 171 | | Expr::Repeat(_)
|
| 172 | | Expr::Return(_)
|
| 173 | | Expr::Struct(_)
|
| 174 | | Expr::TryBlock(_)
|
| 175 | | Expr::Tuple(_)
|
| 176 | | Expr::Unary(_)
|
| 177 | | Expr::Unsafe(_)
|
| 178 | | Expr::Verbatim(_)
|
| 179 | | Expr::Yield(_) => return false,
|
| 180 | }
|
| 181 | }
|
| 182 | }
|
| 183 |
|
| 184 | |
| 185 | #[cfg(feature = "full")]
|
| 186 | pub(crate) fn expr_trailing_brace(mut expr: &Expr) -> bool {
|
| 187 | loop {
|
| 188 | match expr {
|
| 189 | Expr::Async(_)
|
| 190 | | Expr::Block(_)
|
| 191 | | Expr::Const(_)
|
| 192 | | Expr::ForLoop(_)
|
| 193 | | Expr::If(_)
|
| 194 | | Expr::Loop(_)
|
| 195 | | Expr::Match(_)
|
| 196 | | Expr::Struct(_)
|
| 197 | | Expr::TryBlock(_)
|
| 198 | | Expr::Unsafe(_)
|
| 199 | | Expr::While(_) => return true,
|
| 200 |
|
| 201 | Expr::Assign(e) => expr = &e.right,
|
| 202 | Expr::Binary(e) => expr = &e.right,
|
| 203 | Expr::Break(e) => match &e.expr {
|
| 204 | Some(e) => expr = e,
|
| 205 | None => return false,
|
| 206 | },
|
| 207 | Expr::Cast(e) => return type_trailing_brace(&e.ty),
|
| 208 | Expr::Closure(e) => expr = &e.body,
|
| 209 | Expr::Let(e) => expr = &e.expr,
|
| 210 | Expr::Macro(e) => return e.mac.delimiter.is_brace(),
|
| 211 | Expr::Range(e) => match &e.end {
|
| 212 | Some(end) => expr = end,
|
| 213 | None => return false,
|
| 214 | },
|
| 215 | Expr::RawAddr(e) => expr = &e.expr,
|
| 216 | Expr::Reference(e) => expr = &e.expr,
|
| 217 | Expr::Return(e) => match &e.expr {
|
| 218 | Some(e) => expr = e,
|
| 219 | None => return false,
|
| 220 | },
|
| 221 | Expr::Unary(e) => expr = &e.expr,
|
| 222 | Expr::Verbatim(e) => return tokens_trailing_brace(e),
|
| 223 | Expr::Yield(e) => match &e.expr {
|
| 224 | Some(e) => expr = e,
|
| 225 | None => return false,
|
| 226 | },
|
| 227 |
|
| 228 | Expr::Array(_)
|
| 229 | | Expr::Await(_)
|
| 230 | | Expr::Call(_)
|
| 231 | | Expr::Continue(_)
|
| 232 | | Expr::Field(_)
|
| 233 | | Expr::Group(_)
|
| 234 | | Expr::Index(_)
|
| 235 | | Expr::Infer(_)
|
| 236 | | Expr::Lit(_)
|
| 237 | | Expr::MethodCall(_)
|
| 238 | | Expr::Paren(_)
|
| 239 | | Expr::Path(_)
|
| 240 | | Expr::Repeat(_)
|
| 241 | | Expr::Try(_)
|
| 242 | | Expr::Tuple(_) => return false,
|
| 243 | }
|
| 244 | }
|
| 245 |
|
| 246 | fn type_trailing_brace(mut ty: &Type) -> bool {
|
| 247 | loop {
|
| 248 | match ty {
|
| 249 | Type::BareFn(t) => match &t.output {
|
| 250 | ReturnType::Default => return false,
|
| 251 | ReturnType::Type(_, ret) => ty = ret,
|
| 252 | },
|
| 253 | Type::ImplTrait(t) => match last_type_in_bounds(&t.bounds) {
|
| 254 | ControlFlow::Break(trailing_brace) => return trailing_brace,
|
| 255 | ControlFlow::Continue(t) => ty = t,
|
| 256 | },
|
| 257 | Type::Macro(t) => return t.mac.delimiter.is_brace(),
|
| 258 | Type::Path(t) => match last_type_in_path(&t.path) {
|
| 259 | Some(t) => ty = t,
|
| 260 | None => return false,
|
| 261 | },
|
| 262 | Type::Ptr(t) => ty = &t.elem,
|
| 263 | Type::Reference(t) => ty = &t.elem,
|
| 264 | Type::TraitObject(t) => match last_type_in_bounds(&t.bounds) {
|
| 265 | ControlFlow::Break(trailing_brace) => return trailing_brace,
|
| 266 | ControlFlow::Continue(t) => ty = t,
|
| 267 | },
|
| 268 | Type::Verbatim(t) => return tokens_trailing_brace(t),
|
| 269 |
|
| 270 | Type::Array(_)
|
| 271 | | Type::Group(_)
|
| 272 | | Type::Infer(_)
|
| 273 | | Type::Never(_)
|
| 274 | | Type::Paren(_)
|
| 275 | | Type::Slice(_)
|
| 276 | | Type::Tuple(_) => return false,
|
| 277 | }
|
| 278 | }
|
| 279 | }
|
| 280 |
|
| 281 | fn last_type_in_path(path: &Path) -> Option<&Type> {
|
| 282 | match &path.segments.last().unwrap().arguments {
|
| 283 | PathArguments::None | PathArguments::AngleBracketed(_) => None,
|
| 284 | PathArguments::Parenthesized(arg) => match &arg.output {
|
| 285 | ReturnType::Default => None,
|
| 286 | ReturnType::Type(_, ret) => Some(ret),
|
| 287 | },
|
| 288 | }
|
| 289 | }
|
| 290 |
|
| 291 | fn last_type_in_bounds(
|
| 292 | bounds: &Punctuated<TypeParamBound, Token![+]>,
|
| 293 | ) -> ControlFlow<bool, &Type> {
|
| 294 | match bounds.last().unwrap() {
|
| 295 | TypeParamBound::Trait(t) => match last_type_in_path(&t.path) {
|
| 296 | Some(t) => ControlFlow::Continue(t),
|
| 297 | None => ControlFlow::Break(false),
|
| 298 | },
|
| 299 | TypeParamBound::Lifetime(_) | TypeParamBound::PreciseCapture(_) => {
|
| 300 | ControlFlow::Break(false)
|
| 301 | }
|
| 302 | TypeParamBound::Verbatim(t) => ControlFlow::Break(tokens_trailing_brace(t)),
|
| 303 | }
|
| 304 | }
|
| 305 |
|
| 306 | fn tokens_trailing_brace(tokens: &TokenStream) -> bool {
|
| 307 | if let Some(TokenTree::Group(last)) = tokens.clone().into_iter().last() {
|
| 308 | last.delimiter() == Delimiter::Brace
|
| 309 | } else {
|
| 310 | false
|
| 311 | }
|
| 312 | }
|
| 313 | }
|