rustfmt_nightly/parse/macros/
cfg_match.rs1use std::panic::{AssertUnwindSafe, catch_unwind};
2
3use rustc_ast::ast;
4use rustc_ast::token::TokenKind;
5use rustc_parse::exp;
6use rustc_parse::parser::{AllowConstBlockItems, ForceCollect};
7
8use crate::parse::macros::build_stream_parser;
9use crate::parse::session::ParseSess;
10
11pub(crate) fn parse_cfg_match<'a>(
12 psess: &'a ParseSess,
13 mac: &'a ast::MacCall,
14) -> Result<Vec<ast::Item>, &'static str> {
15 match catch_unwind(AssertUnwindSafe(|| parse_cfg_match_inner(psess, mac))) {
16 Ok(Ok(items)) => Ok(items),
17 Ok(err @ Err(_)) => err,
18 Err(..) => Err("failed to parse cfg_match!"),
19 }
20}
21
22fn parse_cfg_match_inner<'a>(
23 psess: &'a ParseSess,
24 mac: &'a ast::MacCall,
25) -> Result<Vec<ast::Item>, &'static str> {
26 let ts = mac.args.tokens.clone();
27 let mut parser = build_stream_parser(psess.inner(), ts);
28
29 if parser.token == TokenKind::OpenBrace {
30 return Err("Expression position cfg_match! not yet supported");
31 }
32
33 let mut items = vec![];
34
35 while parser.token.kind != TokenKind::Eof {
36 if !parser.eat_keyword(exp!(Underscore)) {
37 parser.parse_attr_item(ForceCollect::No).map_err(|e| {
38 e.cancel();
39 "Failed to parse attr item"
40 })?;
41 }
42
43 if !parser.eat(exp!(FatArrow)) {
44 return Err("Expected a fat arrow");
45 }
46
47 if !parser.eat(exp!(OpenBrace)) {
48 return Err("Expected an opening brace");
49 }
50
51 while parser.token != TokenKind::CloseBrace && parser.token.kind != TokenKind::Eof {
52 let item = match parser
53 .parse_item(ForceCollect::No, AllowConstBlockItems::DoesNotMatter)
54 {
55 Ok(Some(item_ptr)) => *item_ptr,
56 Ok(None) => continue,
57 Err(err) => {
58 err.cancel();
59 parser.psess.dcx().reset_err_count();
60 return Err(
61 "Expected item inside cfg_match block, but failed to parse it as an item",
62 );
63 }
64 };
65 if let ast::ItemKind::Mod(..) = item.kind {
66 items.push(item);
67 }
68 }
69
70 if !parser.eat(exp!(CloseBrace)) {
71 return Err("Expected a closing brace");
72 }
73
74 if parser.eat(exp!(Eof)) {
75 break;
76 }
77 }
78
79 Ok(items)
80}