diff options
| author | David Tolnay <dtolnay@gmail.com> | 2022-01-14 14:52:04 -0800 |
|---|---|---|
| committer | David Tolnay <dtolnay@gmail.com> | 2022-01-18 11:14:42 -0800 |
| commit | a6c9d8f524c035b71c15058f3682dc684c268d82 (patch) | |
| tree | a01644decab845224b84a12dee91c20565f514e0 | |
| parent | c70c646a0f7d7e9a1a481d5ae5b26b140cfd4cf2 (diff) | |
| download | rust-a6c9d8f524c035b71c15058f3682dc684c268d82.tar.gz rust-a6c9d8f524c035b71c15058f3682dc684c268d82.zip | |
Invert the keyword list to list only *no* space before delim
| -rw-r--r-- | src/librustdoc/clean/render_macro_matchers.rs | 98 |
1 files changed, 60 insertions, 38 deletions
diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs index a6faa0d6857..dff370ab750 100644 --- a/src/librustdoc/clean/render_macro_matchers.rs +++ b/src/librustdoc/clean/render_macro_matchers.rs @@ -5,7 +5,8 @@ use rustc_ast_pretty::pprust::PrintState; use rustc_middle::ty::TyCtxt; use rustc_session::parse::ParseSess; use rustc_span::source_map::FilePathMapping; -use rustc_span::symbol::{kw, Symbol}; +use rustc_span::symbol::{kw, Ident, Symbol}; +use rustc_span::Span; /// Render a macro matcher in a format suitable for displaying to the user /// as part of an item declaration. @@ -153,7 +154,7 @@ fn print_tts(printer: &mut Printer<'_>, tts: &TokenStream) { } (Pound, token::Not) => (false, PoundBang), (_, token::Ident(symbol, /* is_raw */ false)) - if !usually_needs_space_between_keyword_and_open_delim(*symbol) => + if !usually_needs_space_between_keyword_and_open_delim(*symbol, tt.span) => { (true, Ident) } @@ -177,42 +178,63 @@ fn print_tts(printer: &mut Printer<'_>, tts: &TokenStream) { } } -// This rough subset of keywords is listed here to distinguish tokens resembling -// `f(0)` (no space between ident and paren) from tokens resembling `if let (0, -// 0) = x` (space between ident and paren). -fn usually_needs_space_between_keyword_and_open_delim(symbol: Symbol) -> bool { +fn usually_needs_space_between_keyword_and_open_delim(symbol: Symbol, span: Span) -> bool { + let ident = Ident { name: symbol, span }; + let is_keyword = ident.is_used_keyword() || ident.is_unused_keyword(); + if !is_keyword { + // An identifier that is not a keyword usually does not need a space + // before an open delim. For example: `f(0)` or `f[0]`. + return false; + } + match symbol { - kw::As - | kw::Box - | kw::Break - | kw::Const - | kw::Continue - | kw::Crate - | kw::Else - | kw::Enum - | kw::Extern - | kw::For - | kw::If - | kw::Impl - | kw::In - | kw::Let - | kw::Loop - | kw::Macro - | kw::Match - | kw::Mod - | kw::Move - | kw::Mut - | kw::Ref - | kw::Return - | kw::Static - | kw::Struct - | kw::Trait - | kw::Type - | kw::Unsafe - | kw::Use - | kw::Where - | kw::While - | kw::Yield => true, - _ => false, + // No space after keywords that are syntactically an expression. For + // example: a tuple struct created with `let _ = Self(0, 0)`, or if + // someone has `impl Index<MyStruct> for bool` then `true[MyStruct]`. + kw::False | kw::SelfLower | kw::SelfUpper | kw::True => false, + + // No space, as in `let _: fn();` + kw::Fn => false, + + // No space, as in `pub(crate) type T;` + kw::Pub => false, + + // No space for keywords that can end an expression, as in `fut.await()` + // where fut's Output type is `fn()`. + kw::Await => false, + + // Otherwise space after keyword. Some examples: + // + // `expr as [T; 2]` + // ^ + // `box (tuple,)` + // ^ + // `break (tuple,)` + // ^ + // `type T = dyn (Fn() -> dyn Trait) + Send;` + // ^ + // `for (tuple,) in iter {}` + // ^ + // `if (tuple,) == v {}` + // ^ + // `impl [T] {}` + // ^ + // `for x in [..] {}` + // ^ + // `let () = unit;` + // ^ + // `match [x, y] {...}` + // ^ + // `&mut (x as T)` + // ^ + // `return [];` + // ^ + // `fn f<T>() where (): Into<T>` + // ^ + // `while (a + b).what() {}` + // ^ + // `yield [];` + // ^ + _ => true, } } |
