Skip to content

Commit 97c3e48

Browse files
refactor: encapsulate cfg_if parsing within parse mod
1 parent 6298756 commit 97c3e48

File tree

4 files changed

+98
-83
lines changed

4 files changed

+98
-83
lines changed

Diff for: src/modules/visitor.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc_ast::visit::Visitor;
33
use rustc_span::Symbol;
44

55
use crate::attr::MetaVisitor;
6-
use crate::parse::parser::Parser;
6+
use crate::parse::macros::cfg_if::parse_cfg_if;
77
use crate::parse::session::ParseSess;
88

99
pub(crate) struct ModItem {
@@ -62,7 +62,7 @@ impl<'a, 'ast: 'a> CfgIfVisitor<'a> {
6262
}
6363
};
6464

65-
let items = Parser::parse_cfg_if(self.parse_sess, mac)?;
65+
let items = parse_cfg_if(self.parse_sess, mac)?;
6666
self.mods
6767
.append(&mut items.into_iter().map(|item| ModItem { item }).collect());
6868

Diff for: src/parse/macros/cfg_if.rs

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
use std::panic::{catch_unwind, AssertUnwindSafe};
2+
3+
use rustc_ast::ast;
4+
use rustc_ast::token::{DelimToken, TokenKind};
5+
use rustc_parse::parser::ForceCollect;
6+
use rustc_span::symbol::kw;
7+
8+
use crate::parse::macros::build_stream_parser;
9+
use crate::parse::session::ParseSess;
10+
11+
pub(crate) fn parse_cfg_if<'a>(
12+
sess: &'a ParseSess,
13+
mac: &'a ast::MacCall,
14+
) -> Result<Vec<ast::Item>, &'static str> {
15+
match catch_unwind(AssertUnwindSafe(|| parse_cfg_if_inner(sess, mac))) {
16+
Ok(Ok(items)) => Ok(items),
17+
Ok(err @ Err(_)) => err,
18+
Err(..) => Err("failed to parse cfg_if!"),
19+
}
20+
}
21+
22+
fn parse_cfg_if_inner<'a>(
23+
sess: &'a ParseSess,
24+
mac: &'a ast::MacCall,
25+
) -> Result<Vec<ast::Item>, &'static str> {
26+
let ts = mac.args.inner_tokens();
27+
let mut parser = build_stream_parser(sess.inner(), ts);
28+
29+
let mut items = vec![];
30+
let mut process_if_cfg = true;
31+
32+
while parser.token.kind != TokenKind::Eof {
33+
if process_if_cfg {
34+
if !parser.eat_keyword(kw::If) {
35+
return Err("Expected `if`");
36+
}
37+
// Inner attributes are not actually syntactically permitted here, but we don't
38+
// care about inner vs outer attributes in this position. Our purpose with this
39+
// special case parsing of cfg_if macros is to ensure we can correctly resolve
40+
// imported modules that may have a custom `path` defined.
41+
//
42+
// As such, we just need to advance the parser past the attribute and up to
43+
// to the opening brace.
44+
// See also https://github.com/rust-lang/rust/pull/79433
45+
parser
46+
.parse_attribute(rustc_parse::parser::attr::InnerAttrPolicy::Permitted)
47+
.map_err(|_| "Failed to parse attributes")?;
48+
}
49+
50+
if !parser.eat(&TokenKind::OpenDelim(DelimToken::Brace)) {
51+
return Err("Expected an opening brace");
52+
}
53+
54+
while parser.token != TokenKind::CloseDelim(DelimToken::Brace)
55+
&& parser.token.kind != TokenKind::Eof
56+
{
57+
let item = match parser.parse_item(ForceCollect::No) {
58+
Ok(Some(item_ptr)) => item_ptr.into_inner(),
59+
Ok(None) => continue,
60+
Err(mut err) => {
61+
err.cancel();
62+
parser.sess.span_diagnostic.reset_err_count();
63+
return Err(
64+
"Expected item inside cfg_if block, but failed to parse it as an item",
65+
);
66+
}
67+
};
68+
if let ast::ItemKind::Mod(..) = item.kind {
69+
items.push(item);
70+
}
71+
}
72+
73+
if !parser.eat(&TokenKind::CloseDelim(DelimToken::Brace)) {
74+
return Err("Expected a closing brace");
75+
}
76+
77+
if parser.eat(&TokenKind::Eof) {
78+
break;
79+
}
80+
81+
if !parser.eat_keyword(kw::Else) {
82+
return Err("Expected `else`");
83+
}
84+
85+
process_if_cfg = parser.token.is_keyword(kw::If);
86+
}
87+
88+
Ok(items)
89+
}

Diff for: src/parse/macros/mod.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use rustc_ast::tokenstream::{Cursor, Spacing, TokenStream, TokenTree};
33
use rustc_ast::{ast, ptr};
44
use rustc_parse::parser::{ForceCollect, Parser};
55
use rustc_parse::{stream_to_parser, MACRO_ARGUMENTS};
6+
use rustc_session::parse::ParseSess;
67
use rustc_span::{
78
symbol::{self, kw},
89
BytePos, Span, Symbol, DUMMY_SP,
@@ -11,10 +12,15 @@ use rustc_span::{
1112
use crate::macros::MacroArg;
1213
use crate::rewrite::{Rewrite, RewriteContext};
1314

15+
pub(crate) mod cfg_if;
1416
pub(crate) mod lazy_static;
1517

18+
fn build_stream_parser<'a>(sess: &'a ParseSess, tokens: TokenStream) -> Parser<'a> {
19+
stream_to_parser(sess, tokens, MACRO_ARGUMENTS)
20+
}
21+
1622
fn build_parser<'a>(context: &RewriteContext<'a>, tokens: TokenStream) -> Parser<'a> {
17-
stream_to_parser(context.parse_sess.inner(), tokens, MACRO_ARGUMENTS)
23+
build_stream_parser(context.parse_sess.inner(), tokens)
1824
}
1925

2026
fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {

Diff for: src/parse/parser.rs

-80
Original file line numberDiff line numberDiff line change
@@ -175,84 +175,4 @@ impl<'a> Parser<'a> {
175175
Err(_) => Err(ParserError::ParsePanicError),
176176
}
177177
}
178-
179-
pub(crate) fn parse_cfg_if(
180-
sess: &'a ParseSess,
181-
mac: &'a ast::MacCall,
182-
) -> Result<Vec<ast::Item>, &'static str> {
183-
match catch_unwind(AssertUnwindSafe(|| Parser::parse_cfg_if_inner(sess, mac))) {
184-
Ok(Ok(items)) => Ok(items),
185-
Ok(err @ Err(_)) => err,
186-
Err(..) => Err("failed to parse cfg_if!"),
187-
}
188-
}
189-
190-
fn parse_cfg_if_inner(
191-
sess: &'a ParseSess,
192-
mac: &'a ast::MacCall,
193-
) -> Result<Vec<ast::Item>, &'static str> {
194-
let token_stream = mac.args.inner_tokens();
195-
let mut parser = rustc_parse::stream_to_parser(sess.inner(), token_stream, Some(""));
196-
197-
let mut items = vec![];
198-
let mut process_if_cfg = true;
199-
200-
while parser.token.kind != TokenKind::Eof {
201-
if process_if_cfg {
202-
if !parser.eat_keyword(kw::If) {
203-
return Err("Expected `if`");
204-
}
205-
// Inner attributes are not actually syntactically permitted here, but we don't
206-
// care about inner vs outer attributes in this position. Our purpose with this
207-
// special case parsing of cfg_if macros is to ensure we can correctly resolve
208-
// imported modules that may have a custom `path` defined.
209-
//
210-
// As such, we just need to advance the parser past the attribute and up to
211-
// to the opening brace.
212-
// See also https://github.com/rust-lang/rust/pull/79433
213-
parser
214-
.parse_attribute(rustc_parse::parser::attr::InnerAttrPolicy::Permitted)
215-
.map_err(|_| "Failed to parse attributes")?;
216-
}
217-
218-
if !parser.eat(&TokenKind::OpenDelim(DelimToken::Brace)) {
219-
return Err("Expected an opening brace");
220-
}
221-
222-
while parser.token != TokenKind::CloseDelim(DelimToken::Brace)
223-
&& parser.token.kind != TokenKind::Eof
224-
{
225-
let item = match parser.parse_item(ForceCollect::No) {
226-
Ok(Some(item_ptr)) => item_ptr.into_inner(),
227-
Ok(None) => continue,
228-
Err(mut err) => {
229-
err.cancel();
230-
parser.sess.span_diagnostic.reset_err_count();
231-
return Err(
232-
"Expected item inside cfg_if block, but failed to parse it as an item",
233-
);
234-
}
235-
};
236-
if let ast::ItemKind::Mod(..) = item.kind {
237-
items.push(item);
238-
}
239-
}
240-
241-
if !parser.eat(&TokenKind::CloseDelim(DelimToken::Brace)) {
242-
return Err("Expected a closing brace");
243-
}
244-
245-
if parser.eat(&TokenKind::Eof) {
246-
break;
247-
}
248-
249-
if !parser.eat_keyword(kw::Else) {
250-
return Err("Expected `else`");
251-
}
252-
253-
process_if_cfg = parser.token.is_keyword(kw::If);
254-
}
255-
256-
Ok(items)
257-
}
258178
}

0 commit comments

Comments
 (0)