refactor: encapsulate cfg_if parsing within parse mod
This commit is contained in:
parent
62987562e2
commit
97c3e48834
@ -3,7 +3,7 @@
|
|||||||
use rustc_span::Symbol;
|
use rustc_span::Symbol;
|
||||||
|
|
||||||
use crate::attr::MetaVisitor;
|
use crate::attr::MetaVisitor;
|
||||||
use crate::parse::parser::Parser;
|
use crate::parse::macros::cfg_if::parse_cfg_if;
|
||||||
use crate::parse::session::ParseSess;
|
use crate::parse::session::ParseSess;
|
||||||
|
|
||||||
pub(crate) struct ModItem {
|
pub(crate) struct ModItem {
|
||||||
@ -62,7 +62,7 @@ fn visit_mac_inner(&mut self, mac: &'ast ast::MacCall) -> Result<(), &'static st
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let items = Parser::parse_cfg_if(self.parse_sess, mac)?;
|
let items = parse_cfg_if(self.parse_sess, mac)?;
|
||||||
self.mods
|
self.mods
|
||||||
.append(&mut items.into_iter().map(|item| ModItem { item }).collect());
|
.append(&mut items.into_iter().map(|item| ModItem { item }).collect());
|
||||||
|
|
||||||
|
89
src/parse/macros/cfg_if.rs
Normal file
89
src/parse/macros/cfg_if.rs
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
use std::panic::{catch_unwind, AssertUnwindSafe};
|
||||||
|
|
||||||
|
use rustc_ast::ast;
|
||||||
|
use rustc_ast::token::{DelimToken, TokenKind};
|
||||||
|
use rustc_parse::parser::ForceCollect;
|
||||||
|
use rustc_span::symbol::kw;
|
||||||
|
|
||||||
|
use crate::parse::macros::build_stream_parser;
|
||||||
|
use crate::parse::session::ParseSess;
|
||||||
|
|
||||||
|
pub(crate) fn parse_cfg_if<'a>(
|
||||||
|
sess: &'a ParseSess,
|
||||||
|
mac: &'a ast::MacCall,
|
||||||
|
) -> Result<Vec<ast::Item>, &'static str> {
|
||||||
|
match catch_unwind(AssertUnwindSafe(|| parse_cfg_if_inner(sess, mac))) {
|
||||||
|
Ok(Ok(items)) => Ok(items),
|
||||||
|
Ok(err @ Err(_)) => err,
|
||||||
|
Err(..) => Err("failed to parse cfg_if!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_cfg_if_inner<'a>(
|
||||||
|
sess: &'a ParseSess,
|
||||||
|
mac: &'a ast::MacCall,
|
||||||
|
) -> Result<Vec<ast::Item>, &'static str> {
|
||||||
|
let ts = mac.args.inner_tokens();
|
||||||
|
let mut parser = build_stream_parser(sess.inner(), ts);
|
||||||
|
|
||||||
|
let mut items = vec![];
|
||||||
|
let mut process_if_cfg = true;
|
||||||
|
|
||||||
|
while parser.token.kind != TokenKind::Eof {
|
||||||
|
if process_if_cfg {
|
||||||
|
if !parser.eat_keyword(kw::If) {
|
||||||
|
return Err("Expected `if`");
|
||||||
|
}
|
||||||
|
// Inner attributes are not actually syntactically permitted here, but we don't
|
||||||
|
// care about inner vs outer attributes in this position. Our purpose with this
|
||||||
|
// special case parsing of cfg_if macros is to ensure we can correctly resolve
|
||||||
|
// imported modules that may have a custom `path` defined.
|
||||||
|
//
|
||||||
|
// As such, we just need to advance the parser past the attribute and up to
|
||||||
|
// to the opening brace.
|
||||||
|
// See also https://github.com/rust-lang/rust/pull/79433
|
||||||
|
parser
|
||||||
|
.parse_attribute(rustc_parse::parser::attr::InnerAttrPolicy::Permitted)
|
||||||
|
.map_err(|_| "Failed to parse attributes")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !parser.eat(&TokenKind::OpenDelim(DelimToken::Brace)) {
|
||||||
|
return Err("Expected an opening brace");
|
||||||
|
}
|
||||||
|
|
||||||
|
while parser.token != TokenKind::CloseDelim(DelimToken::Brace)
|
||||||
|
&& parser.token.kind != TokenKind::Eof
|
||||||
|
{
|
||||||
|
let item = match parser.parse_item(ForceCollect::No) {
|
||||||
|
Ok(Some(item_ptr)) => item_ptr.into_inner(),
|
||||||
|
Ok(None) => continue,
|
||||||
|
Err(mut err) => {
|
||||||
|
err.cancel();
|
||||||
|
parser.sess.span_diagnostic.reset_err_count();
|
||||||
|
return Err(
|
||||||
|
"Expected item inside cfg_if block, but failed to parse it as an item",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if let ast::ItemKind::Mod(..) = item.kind {
|
||||||
|
items.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !parser.eat(&TokenKind::CloseDelim(DelimToken::Brace)) {
|
||||||
|
return Err("Expected a closing brace");
|
||||||
|
}
|
||||||
|
|
||||||
|
if parser.eat(&TokenKind::Eof) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !parser.eat_keyword(kw::Else) {
|
||||||
|
return Err("Expected `else`");
|
||||||
|
}
|
||||||
|
|
||||||
|
process_if_cfg = parser.token.is_keyword(kw::If);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(items)
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
use rustc_ast::{ast, ptr};
|
use rustc_ast::{ast, ptr};
|
||||||
use rustc_parse::parser::{ForceCollect, Parser};
|
use rustc_parse::parser::{ForceCollect, Parser};
|
||||||
use rustc_parse::{stream_to_parser, MACRO_ARGUMENTS};
|
use rustc_parse::{stream_to_parser, MACRO_ARGUMENTS};
|
||||||
|
use rustc_session::parse::ParseSess;
|
||||||
use rustc_span::{
|
use rustc_span::{
|
||||||
symbol::{self, kw},
|
symbol::{self, kw},
|
||||||
BytePos, Span, Symbol, DUMMY_SP,
|
BytePos, Span, Symbol, DUMMY_SP,
|
||||||
@ -11,10 +12,15 @@
|
|||||||
use crate::macros::MacroArg;
|
use crate::macros::MacroArg;
|
||||||
use crate::rewrite::{Rewrite, RewriteContext};
|
use crate::rewrite::{Rewrite, RewriteContext};
|
||||||
|
|
||||||
|
pub(crate) mod cfg_if;
|
||||||
pub(crate) mod lazy_static;
|
pub(crate) mod lazy_static;
|
||||||
|
|
||||||
|
fn build_stream_parser<'a>(sess: &'a ParseSess, tokens: TokenStream) -> Parser<'a> {
|
||||||
|
stream_to_parser(sess, tokens, MACRO_ARGUMENTS)
|
||||||
|
}
|
||||||
|
|
||||||
fn build_parser<'a>(context: &RewriteContext<'a>, tokens: TokenStream) -> Parser<'a> {
|
fn build_parser<'a>(context: &RewriteContext<'a>, tokens: TokenStream) -> Parser<'a> {
|
||||||
stream_to_parser(context.parse_sess.inner(), tokens, MACRO_ARGUMENTS)
|
build_stream_parser(context.parse_sess.inner(), tokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
|
fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
|
||||||
|
@ -175,84 +175,4 @@ fn parse_crate_mod(&mut self) -> Result<ast::Crate, ParserError> {
|
|||||||
Err(_) => Err(ParserError::ParsePanicError),
|
Err(_) => Err(ParserError::ParsePanicError),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn parse_cfg_if(
|
|
||||||
sess: &'a ParseSess,
|
|
||||||
mac: &'a ast::MacCall,
|
|
||||||
) -> Result<Vec<ast::Item>, &'static str> {
|
|
||||||
match catch_unwind(AssertUnwindSafe(|| Parser::parse_cfg_if_inner(sess, mac))) {
|
|
||||||
Ok(Ok(items)) => Ok(items),
|
|
||||||
Ok(err @ Err(_)) => err,
|
|
||||||
Err(..) => Err("failed to parse cfg_if!"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_cfg_if_inner(
|
|
||||||
sess: &'a ParseSess,
|
|
||||||
mac: &'a ast::MacCall,
|
|
||||||
) -> Result<Vec<ast::Item>, &'static str> {
|
|
||||||
let token_stream = mac.args.inner_tokens();
|
|
||||||
let mut parser = rustc_parse::stream_to_parser(sess.inner(), token_stream, Some(""));
|
|
||||||
|
|
||||||
let mut items = vec![];
|
|
||||||
let mut process_if_cfg = true;
|
|
||||||
|
|
||||||
while parser.token.kind != TokenKind::Eof {
|
|
||||||
if process_if_cfg {
|
|
||||||
if !parser.eat_keyword(kw::If) {
|
|
||||||
return Err("Expected `if`");
|
|
||||||
}
|
|
||||||
// Inner attributes are not actually syntactically permitted here, but we don't
|
|
||||||
// care about inner vs outer attributes in this position. Our purpose with this
|
|
||||||
// special case parsing of cfg_if macros is to ensure we can correctly resolve
|
|
||||||
// imported modules that may have a custom `path` defined.
|
|
||||||
//
|
|
||||||
// As such, we just need to advance the parser past the attribute and up to
|
|
||||||
// to the opening brace.
|
|
||||||
// See also https://github.com/rust-lang/rust/pull/79433
|
|
||||||
parser
|
|
||||||
.parse_attribute(rustc_parse::parser::attr::InnerAttrPolicy::Permitted)
|
|
||||||
.map_err(|_| "Failed to parse attributes")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !parser.eat(&TokenKind::OpenDelim(DelimToken::Brace)) {
|
|
||||||
return Err("Expected an opening brace");
|
|
||||||
}
|
|
||||||
|
|
||||||
while parser.token != TokenKind::CloseDelim(DelimToken::Brace)
|
|
||||||
&& parser.token.kind != TokenKind::Eof
|
|
||||||
{
|
|
||||||
let item = match parser.parse_item(ForceCollect::No) {
|
|
||||||
Ok(Some(item_ptr)) => item_ptr.into_inner(),
|
|
||||||
Ok(None) => continue,
|
|
||||||
Err(mut err) => {
|
|
||||||
err.cancel();
|
|
||||||
parser.sess.span_diagnostic.reset_err_count();
|
|
||||||
return Err(
|
|
||||||
"Expected item inside cfg_if block, but failed to parse it as an item",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if let ast::ItemKind::Mod(..) = item.kind {
|
|
||||||
items.push(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !parser.eat(&TokenKind::CloseDelim(DelimToken::Brace)) {
|
|
||||||
return Err("Expected a closing brace");
|
|
||||||
}
|
|
||||||
|
|
||||||
if parser.eat(&TokenKind::Eof) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !parser.eat_keyword(kw::Else) {
|
|
||||||
return Err("Expected `else`");
|
|
||||||
}
|
|
||||||
|
|
||||||
process_if_cfg = parser.token.is_keyword(kw::If);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(items)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user