Merge commit '4a053f206f
' into sync-rustfmt-subtree
This commit is contained in:
commit
521fdcbe4d
44 changed files with 710 additions and 410 deletions
|
@ -1,3 +1,3 @@
|
||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly-2021-11-08"
|
channel = "nightly-2021-12-29"
|
||||||
components = ["rustc-dev"]
|
components = ["rustc-dev"]
|
||||||
|
|
|
@ -26,7 +26,7 @@ fn main() {
|
||||||
let exit_code = match execute(&opts) {
|
let exit_code = match execute(&opts) {
|
||||||
Ok(code) => code,
|
Ok(code) => code,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("{}", e.to_string());
|
eprintln!("{}", e);
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -236,21 +236,21 @@ fn rewrite_closure_fn_decl(
|
||||||
context: &RewriteContext<'_>,
|
context: &RewriteContext<'_>,
|
||||||
shape: Shape,
|
shape: Shape,
|
||||||
) -> Option<(String, usize)> {
|
) -> Option<(String, usize)> {
|
||||||
|
let immovable = if movability == ast::Movability::Static {
|
||||||
|
"static "
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
};
|
||||||
let is_async = if asyncness.is_async() { "async " } else { "" };
|
let is_async = if asyncness.is_async() { "async " } else { "" };
|
||||||
let mover = if capture == ast::CaptureBy::Value {
|
let mover = if capture == ast::CaptureBy::Value {
|
||||||
"move "
|
"move "
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
let immovable = if movability == ast::Movability::Static {
|
|
||||||
"static "
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
};
|
|
||||||
// 4 = "|| {".len(), which is overconservative when the closure consists of
|
// 4 = "|| {".len(), which is overconservative when the closure consists of
|
||||||
// a single expression.
|
// a single expression.
|
||||||
let nested_shape = shape
|
let nested_shape = shape
|
||||||
.shrink_left(is_async.len() + mover.len() + immovable.len())?
|
.shrink_left(immovable.len() + is_async.len() + mover.len())?
|
||||||
.sub_width(4)?;
|
.sub_width(4)?;
|
||||||
|
|
||||||
// 1 = |
|
// 1 = |
|
||||||
|
@ -288,7 +288,7 @@ fn rewrite_closure_fn_decl(
|
||||||
.tactic(tactic)
|
.tactic(tactic)
|
||||||
.preserve_newline(true);
|
.preserve_newline(true);
|
||||||
let list_str = write_list(&item_vec, &fmt)?;
|
let list_str = write_list(&item_vec, &fmt)?;
|
||||||
let mut prefix = format!("{}{}{}|{}|", is_async, immovable, mover, list_str);
|
let mut prefix = format!("{}{}{}|{}|", immovable, is_async, mover, list_str);
|
||||||
|
|
||||||
if !ret_str.is_empty() {
|
if !ret_str.is_empty() {
|
||||||
if prefix.contains('\n') {
|
if prefix.contains('\n') {
|
||||||
|
|
|
@ -13,9 +13,9 @@ use thiserror::Error;
|
||||||
|
|
||||||
/// A range of lines in a file, inclusive of both ends.
|
/// A range of lines in a file, inclusive of both ends.
|
||||||
pub struct LineRange {
|
pub struct LineRange {
|
||||||
pub file: Lrc<SourceFile>,
|
pub(crate) file: Lrc<SourceFile>,
|
||||||
pub lo: usize,
|
pub(crate) lo: usize,
|
||||||
pub hi: usize,
|
pub(crate) hi: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Defines the name of an input - either a file or stdin.
|
/// Defines the name of an input - either a file or stdin.
|
||||||
|
@ -75,7 +75,7 @@ impl Serialize for FileName {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LineRange {
|
impl LineRange {
|
||||||
pub fn file_name(&self) -> FileName {
|
pub(crate) fn file_name(&self) -> FileName {
|
||||||
self.file.name.clone().into()
|
self.file.name.clone().into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,24 +218,24 @@ pub enum Verbosity {
|
||||||
pub struct WidthHeuristics {
|
pub struct WidthHeuristics {
|
||||||
// Maximum width of the args of a function call before falling back
|
// Maximum width of the args of a function call before falling back
|
||||||
// to vertical formatting.
|
// to vertical formatting.
|
||||||
pub fn_call_width: usize,
|
pub(crate) fn_call_width: usize,
|
||||||
// Maximum width of the args of a function-like attributes before falling
|
// Maximum width of the args of a function-like attributes before falling
|
||||||
// back to vertical formatting.
|
// back to vertical formatting.
|
||||||
pub attr_fn_like_width: usize,
|
pub(crate) attr_fn_like_width: usize,
|
||||||
// Maximum width in the body of a struct lit before falling back to
|
// Maximum width in the body of a struct lit before falling back to
|
||||||
// vertical formatting.
|
// vertical formatting.
|
||||||
pub struct_lit_width: usize,
|
pub(crate) struct_lit_width: usize,
|
||||||
// Maximum width in the body of a struct variant before falling back
|
// Maximum width in the body of a struct variant before falling back
|
||||||
// to vertical formatting.
|
// to vertical formatting.
|
||||||
pub struct_variant_width: usize,
|
pub(crate) struct_variant_width: usize,
|
||||||
// Maximum width of an array literal before falling back to vertical
|
// Maximum width of an array literal before falling back to vertical
|
||||||
// formatting.
|
// formatting.
|
||||||
pub array_width: usize,
|
pub(crate) array_width: usize,
|
||||||
// Maximum length of a chain to fit on a single line.
|
// Maximum length of a chain to fit on a single line.
|
||||||
pub chain_width: usize,
|
pub(crate) chain_width: usize,
|
||||||
// Maximum line length for single line if-else expressions. A value
|
// Maximum line length for single line if-else expressions. A value
|
||||||
// of zero means always break if-else expressions.
|
// of zero means always break if-else expressions.
|
||||||
pub single_line_if_else_max_width: usize,
|
pub(crate) single_line_if_else_max_width: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for WidthHeuristics {
|
impl fmt::Display for WidthHeuristics {
|
||||||
|
|
|
@ -108,9 +108,21 @@ pub(crate) fn format_expr(
|
||||||
ast::ExprKind::Unary(op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape),
|
ast::ExprKind::Unary(op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape),
|
||||||
ast::ExprKind::Struct(ref struct_expr) => {
|
ast::ExprKind::Struct(ref struct_expr) => {
|
||||||
let ast::StructExpr {
|
let ast::StructExpr {
|
||||||
fields, path, rest, ..
|
qself,
|
||||||
|
fields,
|
||||||
|
path,
|
||||||
|
rest,
|
||||||
} = &**struct_expr;
|
} = &**struct_expr;
|
||||||
rewrite_struct_lit(context, path, fields, rest, &expr.attrs, expr.span, shape)
|
rewrite_struct_lit(
|
||||||
|
context,
|
||||||
|
path,
|
||||||
|
qself.as_ref(),
|
||||||
|
fields,
|
||||||
|
rest,
|
||||||
|
&expr.attrs,
|
||||||
|
expr.span,
|
||||||
|
shape,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
ast::ExprKind::Tup(ref items) => {
|
ast::ExprKind::Tup(ref items) => {
|
||||||
rewrite_tuple(context, items.iter(), expr.span, shape, items.len() == 1)
|
rewrite_tuple(context, items.iter(), expr.span, shape, items.len() == 1)
|
||||||
|
@ -1511,6 +1523,7 @@ fn struct_lit_can_be_aligned(fields: &[ast::ExprField], has_base: bool) -> bool
|
||||||
fn rewrite_struct_lit<'a>(
|
fn rewrite_struct_lit<'a>(
|
||||||
context: &RewriteContext<'_>,
|
context: &RewriteContext<'_>,
|
||||||
path: &ast::Path,
|
path: &ast::Path,
|
||||||
|
qself: Option<&ast::QSelf>,
|
||||||
fields: &'a [ast::ExprField],
|
fields: &'a [ast::ExprField],
|
||||||
struct_rest: &ast::StructRest,
|
struct_rest: &ast::StructRest,
|
||||||
attrs: &[ast::Attribute],
|
attrs: &[ast::Attribute],
|
||||||
|
@ -1527,7 +1540,7 @@ fn rewrite_struct_lit<'a>(
|
||||||
|
|
||||||
// 2 = " {".len()
|
// 2 = " {".len()
|
||||||
let path_shape = shape.sub_width(2)?;
|
let path_shape = shape.sub_width(2)?;
|
||||||
let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?;
|
let path_str = rewrite_path(context, PathContext::Expr, qself, path, path_shape)?;
|
||||||
|
|
||||||
let has_base_or_rest = match struct_rest {
|
let has_base_or_rest = match struct_rest {
|
||||||
ast::StructRest::None if fields.is_empty() => return Some(format!("{} {{}}", path_str)),
|
ast::StructRest::None if fields.is_empty() => return Some(format!("{} {{}}", path_str)),
|
||||||
|
@ -2003,9 +2016,7 @@ fn choose_rhs<R: Rewrite>(
|
||||||
has_rhs_comment: bool,
|
has_rhs_comment: bool,
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
match orig_rhs {
|
match orig_rhs {
|
||||||
Some(ref new_str) if new_str.is_empty() => {
|
Some(ref new_str) if new_str.is_empty() => Some(String::new()),
|
||||||
return Some(String::new());
|
|
||||||
}
|
|
||||||
Some(ref new_str)
|
Some(ref new_str)
|
||||||
if !new_str.contains('\n') && unicode_str_width(new_str) <= shape.width =>
|
if !new_str.contains('\n') && unicode_str_width(new_str) <= shape.width =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,6 +5,7 @@ use std::io::{self, Write};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use rustc_ast::ast;
|
use rustc_ast::ast;
|
||||||
|
use rustc_ast::AstLike;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
use self::newline_style::apply_newline_style;
|
use self::newline_style::apply_newline_style;
|
||||||
|
@ -13,9 +14,9 @@ use crate::config::{Config, FileName, Verbosity};
|
||||||
use crate::formatting::generated::is_generated_file;
|
use crate::formatting::generated::is_generated_file;
|
||||||
use crate::issues::BadIssueSeeker;
|
use crate::issues::BadIssueSeeker;
|
||||||
use crate::modules::Module;
|
use crate::modules::Module;
|
||||||
use crate::syntux::parser::{DirectoryOwnership, Parser, ParserError};
|
use crate::parse::parser::{DirectoryOwnership, Parser, ParserError};
|
||||||
use crate::syntux::session::ParseSess;
|
use crate::parse::session::ParseSess;
|
||||||
use crate::utils::count_newlines;
|
use crate::utils::{contains_skip, count_newlines};
|
||||||
use crate::visitor::FmtVisitor;
|
use crate::visitor::FmtVisitor;
|
||||||
use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session};
|
use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session};
|
||||||
|
|
||||||
|
@ -58,6 +59,39 @@ impl<'b, T: Write + 'b> Session<'b, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Determine if a module should be skipped. True if the module should be skipped, false otherwise.
|
||||||
|
fn should_skip_module<T: FormatHandler>(
|
||||||
|
config: &Config,
|
||||||
|
context: &FormatContext<'_, T>,
|
||||||
|
input_is_stdin: bool,
|
||||||
|
main_file: &FileName,
|
||||||
|
path: &FileName,
|
||||||
|
module: &Module<'_>,
|
||||||
|
) -> bool {
|
||||||
|
if contains_skip(module.attrs()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.skip_children() && path != main_file {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !input_is_stdin && context.ignore_file(path) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !config.format_generated_files() {
|
||||||
|
let source_file = context.parse_session.span_to_file_contents(module.span);
|
||||||
|
let src = source_file.src.as_ref().expect("SourceFile without src");
|
||||||
|
|
||||||
|
if is_generated_file(src) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
// Format an entire crate (or subset of the module tree).
|
// Format an entire crate (or subset of the module tree).
|
||||||
fn format_project<T: FormatHandler>(
|
fn format_project<T: FormatHandler>(
|
||||||
input: Input,
|
input: Input,
|
||||||
|
@ -97,7 +131,12 @@ fn format_project<T: FormatHandler>(
|
||||||
directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaBlock),
|
directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaBlock),
|
||||||
!input_is_stdin && !config.skip_children(),
|
!input_is_stdin && !config.skip_children(),
|
||||||
)
|
)
|
||||||
.visit_crate(&krate)?;
|
.visit_crate(&krate)?
|
||||||
|
.into_iter()
|
||||||
|
.filter(|(path, module)| {
|
||||||
|
!should_skip_module(config, &context, input_is_stdin, &main_file, path, module)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
timer = timer.done_parsing();
|
timer = timer.done_parsing();
|
||||||
|
|
||||||
|
@ -105,15 +144,6 @@ fn format_project<T: FormatHandler>(
|
||||||
context.parse_session.set_silent_emitter();
|
context.parse_session.set_silent_emitter();
|
||||||
|
|
||||||
for (path, module) in files {
|
for (path, module) in files {
|
||||||
let source_file = context.parse_session.span_to_file_contents(module.span);
|
|
||||||
let src = source_file.src.as_ref().expect("SourceFile without src");
|
|
||||||
|
|
||||||
let should_ignore = (!input_is_stdin && context.ignore_file(&path))
|
|
||||||
|| (!config.format_generated_files() && is_generated_file(src));
|
|
||||||
|
|
||||||
if (config.skip_children() && path != main_file) || should_ignore {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
should_emit_verbose(input_is_stdin, config, || println!("Formatting {}", path));
|
should_emit_verbose(input_is_stdin, config, || println!("Formatting {}", path));
|
||||||
context.format_file(path, &module, is_macro_def)?;
|
context.format_file(path, &module, is_macro_def)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1535,7 +1535,7 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
|
||||||
// https://rustc-dev-guide.rust-lang.org/opaque-types-type-alias-impl-trait.html
|
// https://rustc-dev-guide.rust-lang.org/opaque-types-type-alias-impl-trait.html
|
||||||
// https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/items.md#type-aliases
|
// https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/items.md#type-aliases
|
||||||
match (visitor_kind, &op_ty) {
|
match (visitor_kind, &op_ty) {
|
||||||
(Item(_) | AssocTraitItem(_) | ForeignItem(_), Some(ref op_bounds)) => {
|
(Item(_) | AssocTraitItem(_) | ForeignItem(_), Some(op_bounds)) => {
|
||||||
let op = OpaqueType { bounds: op_bounds };
|
let op = OpaqueType { bounds: op_bounds };
|
||||||
rewrite_ty(rw_info, Some(bounds), Some(&op), vis)
|
rewrite_ty(rw_info, Some(bounds), Some(&op), vis)
|
||||||
}
|
}
|
||||||
|
@ -1543,7 +1543,7 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
|
||||||
rewrite_ty(rw_info, Some(bounds), ty_opt, vis)
|
rewrite_ty(rw_info, Some(bounds), ty_opt, vis)
|
||||||
}
|
}
|
||||||
(AssocImplItem(_), _) => {
|
(AssocImplItem(_), _) => {
|
||||||
let result = if let Some(ref op_bounds) = op_ty {
|
let result = if let Some(op_bounds) = op_ty {
|
||||||
let op = OpaqueType { bounds: op_bounds };
|
let op = OpaqueType { bounds: op_bounds };
|
||||||
rewrite_ty(rw_info, Some(bounds), Some(&op), &DEFAULT_VISIBILITY)
|
rewrite_ty(rw_info, Some(bounds), Some(&op), &DEFAULT_VISIBILITY)
|
||||||
} else {
|
} else {
|
||||||
|
@ -3124,7 +3124,7 @@ impl Rewrite for ast::ForeignItem {
|
||||||
let inner_attrs = inner_attributes(&self.attrs);
|
let inner_attrs = inner_attributes(&self.attrs);
|
||||||
let fn_ctxt = visit::FnCtxt::Foreign;
|
let fn_ctxt = visit::FnCtxt::Foreign;
|
||||||
visitor.visit_fn(
|
visitor.visit_fn(
|
||||||
visit::FnKind::Fn(fn_ctxt, self.ident, &sig, &self.vis, Some(body)),
|
visit::FnKind::Fn(fn_ctxt, self.ident, sig, &self.vis, Some(body)),
|
||||||
generics,
|
generics,
|
||||||
&sig.decl,
|
&sig.decl,
|
||||||
self.span,
|
self.span,
|
||||||
|
@ -3137,7 +3137,7 @@ impl Rewrite for ast::ForeignItem {
|
||||||
context,
|
context,
|
||||||
shape.indent,
|
shape.indent,
|
||||||
self.ident,
|
self.ident,
|
||||||
&FnSig::from_method_sig(&sig, generics, &self.vis),
|
&FnSig::from_method_sig(sig, generics, &self.vis),
|
||||||
span,
|
span,
|
||||||
FnBraceStyle::None,
|
FnBraceStyle::None,
|
||||||
)
|
)
|
||||||
|
@ -3166,7 +3166,7 @@ impl Rewrite for ast::ForeignItem {
|
||||||
.map(|s| s + ";")
|
.map(|s| s + ";")
|
||||||
}
|
}
|
||||||
ast::ForeignItemKind::TyAlias(ref ty_alias) => {
|
ast::ForeignItemKind::TyAlias(ref ty_alias) => {
|
||||||
let (kind, span) = (&ItemVisitorKind::ForeignItem(&self), self.span);
|
let (kind, span) = (&ItemVisitorKind::ForeignItem(self), self.span);
|
||||||
rewrite_type_alias(ty_alias, context, shape.indent, kind, span)
|
rewrite_type_alias(ty_alias, context, shape.indent, kind, span)
|
||||||
}
|
}
|
||||||
ast::ForeignItemKind::MacCall(ref mac) => {
|
ast::ForeignItemKind::MacCall(ref mac) => {
|
||||||
|
|
|
@ -15,6 +15,7 @@ extern crate log;
|
||||||
// N.B. these crates are loaded from the sysroot, so they need extern crate.
|
// N.B. these crates are loaded from the sysroot, so they need extern crate.
|
||||||
extern crate rustc_ast;
|
extern crate rustc_ast;
|
||||||
extern crate rustc_ast_pretty;
|
extern crate rustc_ast_pretty;
|
||||||
|
extern crate rustc_builtin_macros;
|
||||||
extern crate rustc_data_structures;
|
extern crate rustc_data_structures;
|
||||||
extern crate rustc_errors;
|
extern crate rustc_errors;
|
||||||
extern crate rustc_expand;
|
extern crate rustc_expand;
|
||||||
|
@ -40,8 +41,8 @@ use crate::emitter::Emitter;
|
||||||
use crate::formatting::{FormatErrorMap, FormattingError, ReportedErrors, SourceFile};
|
use crate::formatting::{FormatErrorMap, FormattingError, ReportedErrors, SourceFile};
|
||||||
use crate::issues::Issue;
|
use crate::issues::Issue;
|
||||||
use crate::modules::ModuleResolutionError;
|
use crate::modules::ModuleResolutionError;
|
||||||
|
use crate::parse::parser::DirectoryOwnership;
|
||||||
use crate::shape::Indent;
|
use crate::shape::Indent;
|
||||||
use crate::syntux::parser::DirectoryOwnership;
|
|
||||||
use crate::utils::indent_next_line;
|
use crate::utils::indent_next_line;
|
||||||
|
|
||||||
pub use crate::config::{
|
pub use crate::config::{
|
||||||
|
@ -77,6 +78,7 @@ mod missed_spans;
|
||||||
pub(crate) mod modules;
|
pub(crate) mod modules;
|
||||||
mod overflow;
|
mod overflow;
|
||||||
mod pairs;
|
mod pairs;
|
||||||
|
mod parse;
|
||||||
mod patterns;
|
mod patterns;
|
||||||
mod release_channel;
|
mod release_channel;
|
||||||
mod reorder;
|
mod reorder;
|
||||||
|
@ -89,7 +91,6 @@ pub(crate) mod source_map;
|
||||||
mod spanned;
|
mod spanned;
|
||||||
mod stmt;
|
mod stmt;
|
||||||
mod string;
|
mod string;
|
||||||
mod syntux;
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test;
|
mod test;
|
||||||
mod types;
|
mod types;
|
||||||
|
|
|
@ -448,10 +448,8 @@ where
|
||||||
true
|
true
|
||||||
} else if starts_with_newline(comment) {
|
} else if starts_with_newline(comment) {
|
||||||
false
|
false
|
||||||
} else if comment.trim().contains('\n') || comment.trim().len() > width {
|
|
||||||
true
|
|
||||||
} else {
|
} else {
|
||||||
false
|
comment.trim().contains('\n') || comment.trim().len() > width
|
||||||
};
|
};
|
||||||
|
|
||||||
rewrite_comment(
|
rewrite_comment(
|
||||||
|
|
|
@ -16,8 +16,6 @@ use rustc_ast::token::{BinOpToken, DelimToken, Token, TokenKind};
|
||||||
use rustc_ast::tokenstream::{Cursor, Spacing, TokenStream, TokenTree};
|
use rustc_ast::tokenstream::{Cursor, Spacing, TokenStream, TokenTree};
|
||||||
use rustc_ast::{ast, ptr};
|
use rustc_ast::{ast, ptr};
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_parse::parser::{ForceCollect, Parser};
|
|
||||||
use rustc_parse::{stream_to_parser, MACRO_ARGUMENTS};
|
|
||||||
use rustc_span::{
|
use rustc_span::{
|
||||||
symbol::{self, kw},
|
symbol::{self, kw},
|
||||||
BytePos, Span, Symbol, DUMMY_SP,
|
BytePos, Span, Symbol, DUMMY_SP,
|
||||||
|
@ -30,6 +28,8 @@ use crate::config::lists::*;
|
||||||
use crate::expr::{rewrite_array, rewrite_assign_rhs, RhsAssignKind};
|
use crate::expr::{rewrite_array, rewrite_assign_rhs, RhsAssignKind};
|
||||||
use crate::lists::{itemize_list, write_list, ListFormatting};
|
use crate::lists::{itemize_list, write_list, ListFormatting};
|
||||||
use crate::overflow;
|
use crate::overflow;
|
||||||
|
use crate::parse::macros::lazy_static::parse_lazy_static;
|
||||||
|
use crate::parse::macros::{parse_expr, parse_macro_args, ParsedMacroArgs};
|
||||||
use crate::rewrite::{Rewrite, RewriteContext};
|
use crate::rewrite::{Rewrite, RewriteContext};
|
||||||
use crate::shape::{Indent, Shape};
|
use crate::shape::{Indent, Shape};
|
||||||
use crate::source_map::SpanUtils;
|
use crate::source_map::SpanUtils;
|
||||||
|
@ -60,7 +60,7 @@ pub(crate) enum MacroArg {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MacroArg {
|
impl MacroArg {
|
||||||
fn is_item(&self) -> bool {
|
pub(crate) fn is_item(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
MacroArg::Item(..) => true,
|
MacroArg::Item(..) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -90,61 +90,6 @@ impl Rewrite for MacroArg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_parser<'a>(context: &RewriteContext<'a>, cursor: Cursor) -> Parser<'a> {
|
|
||||||
stream_to_parser(
|
|
||||||
context.parse_sess.inner(),
|
|
||||||
cursor.collect(),
|
|
||||||
MACRO_ARGUMENTS,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
|
|
||||||
macro_rules! parse_macro_arg {
|
|
||||||
($macro_arg:ident, $parser:expr, $f:expr) => {
|
|
||||||
let mut cloned_parser = (*parser).clone();
|
|
||||||
match $parser(&mut cloned_parser) {
|
|
||||||
Ok(x) => {
|
|
||||||
if parser.sess.span_diagnostic.has_errors() {
|
|
||||||
parser.sess.span_diagnostic.reset_err_count();
|
|
||||||
} else {
|
|
||||||
// Parsing succeeded.
|
|
||||||
*parser = cloned_parser;
|
|
||||||
return Some(MacroArg::$macro_arg($f(x)?));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(mut e) => {
|
|
||||||
e.cancel();
|
|
||||||
parser.sess.span_diagnostic.reset_err_count();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
parse_macro_arg!(
|
|
||||||
Expr,
|
|
||||||
|parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_expr(),
|
|
||||||
|x: ptr::P<ast::Expr>| Some(x)
|
|
||||||
);
|
|
||||||
parse_macro_arg!(
|
|
||||||
Ty,
|
|
||||||
|parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_ty(),
|
|
||||||
|x: ptr::P<ast::Ty>| Some(x)
|
|
||||||
);
|
|
||||||
parse_macro_arg!(
|
|
||||||
Pat,
|
|
||||||
|parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_pat_no_top_alt(None),
|
|
||||||
|x: ptr::P<ast::Pat>| Some(x)
|
|
||||||
);
|
|
||||||
// `parse_item` returns `Option<ptr::P<ast::Item>>`.
|
|
||||||
parse_macro_arg!(
|
|
||||||
Item,
|
|
||||||
|parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_item(ForceCollect::No),
|
|
||||||
|x: Option<ptr::P<ast::Item>>| x
|
|
||||||
);
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Rewrite macro name without using pretty-printer if possible.
|
/// Rewrite macro name without using pretty-printer if possible.
|
||||||
fn rewrite_macro_name(
|
fn rewrite_macro_name(
|
||||||
context: &RewriteContext<'_>,
|
context: &RewriteContext<'_>,
|
||||||
|
@ -232,25 +177,6 @@ pub(crate) fn rewrite_macro(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
|
|
||||||
for &keyword in RUST_KW.iter() {
|
|
||||||
if parser.token.is_keyword(keyword)
|
|
||||||
&& parser.look_ahead(1, |t| {
|
|
||||||
t.kind == TokenKind::Eof
|
|
||||||
|| t.kind == TokenKind::Comma
|
|
||||||
|| t.kind == TokenKind::CloseDelim(DelimToken::NoDelim)
|
|
||||||
})
|
|
||||||
{
|
|
||||||
parser.bump();
|
|
||||||
return Some(MacroArg::Keyword(
|
|
||||||
symbol::Ident::with_dummy_span(keyword),
|
|
||||||
parser.prev_token.span,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rewrite_macro_inner(
|
fn rewrite_macro_inner(
|
||||||
mac: &ast::MacCall,
|
mac: &ast::MacCall,
|
||||||
extra_ident: Option<symbol::Ident>,
|
extra_ident: Option<symbol::Ident>,
|
||||||
|
@ -269,8 +195,9 @@ fn rewrite_macro_inner(
|
||||||
let original_style = macro_style(mac, context);
|
let original_style = macro_style(mac, context);
|
||||||
|
|
||||||
let macro_name = rewrite_macro_name(context, &mac.path, extra_ident);
|
let macro_name = rewrite_macro_name(context, &mac.path, extra_ident);
|
||||||
|
let is_forced_bracket = FORCED_BRACKET_MACROS.contains(&¯o_name[..]);
|
||||||
|
|
||||||
let style = if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) && !is_nested_macro {
|
let style = if is_forced_bracket && !is_nested_macro {
|
||||||
DelimToken::Bracket
|
DelimToken::Bracket
|
||||||
} else {
|
} else {
|
||||||
original_style
|
original_style
|
||||||
|
@ -294,67 +221,21 @@ fn rewrite_macro_inner(
|
||||||
}
|
}
|
||||||
// Format well-known macros which cannot be parsed as a valid AST.
|
// Format well-known macros which cannot be parsed as a valid AST.
|
||||||
if macro_name == "lazy_static!" && !has_comment {
|
if macro_name == "lazy_static!" && !has_comment {
|
||||||
if let success @ Some(..) = format_lazy_static(context, shape, &ts) {
|
if let success @ Some(..) = format_lazy_static(context, shape, ts.trees().collect()) {
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut parser = build_parser(context, ts.trees());
|
let ParsedMacroArgs {
|
||||||
let mut arg_vec = Vec::new();
|
args: arg_vec,
|
||||||
let mut vec_with_semi = false;
|
vec_with_semi,
|
||||||
let mut trailing_comma = false;
|
trailing_comma,
|
||||||
|
} = match parse_macro_args(context, ts, style, is_forced_bracket) {
|
||||||
if DelimToken::Brace != style {
|
Some(args) => args,
|
||||||
loop {
|
None => {
|
||||||
if let Some(arg) = check_keyword(&mut parser) {
|
return return_macro_parse_failure_fallback(context, shape.indent, mac.span());
|
||||||
arg_vec.push(arg);
|
|
||||||
} else if let Some(arg) = parse_macro_arg(&mut parser) {
|
|
||||||
arg_vec.push(arg);
|
|
||||||
} else {
|
|
||||||
return return_macro_parse_failure_fallback(context, shape.indent, mac.span());
|
|
||||||
}
|
|
||||||
|
|
||||||
match parser.token.kind {
|
|
||||||
TokenKind::Eof => break,
|
|
||||||
TokenKind::Comma => (),
|
|
||||||
TokenKind::Semi => {
|
|
||||||
// Try to parse `vec![expr; expr]`
|
|
||||||
if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) {
|
|
||||||
parser.bump();
|
|
||||||
if parser.token.kind != TokenKind::Eof {
|
|
||||||
match parse_macro_arg(&mut parser) {
|
|
||||||
Some(arg) => {
|
|
||||||
arg_vec.push(arg);
|
|
||||||
parser.bump();
|
|
||||||
if parser.token.kind == TokenKind::Eof && arg_vec.len() == 2 {
|
|
||||||
vec_with_semi = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
return return_macro_parse_failure_fallback(
|
|
||||||
context,
|
|
||||||
shape.indent,
|
|
||||||
mac.span(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return return_macro_parse_failure_fallback(context, shape.indent, mac.span());
|
|
||||||
}
|
|
||||||
_ if arg_vec.last().map_or(false, MacroArg::is_item) => continue,
|
|
||||||
_ => return return_macro_parse_failure_fallback(context, shape.indent, mac.span()),
|
|
||||||
}
|
|
||||||
|
|
||||||
parser.bump();
|
|
||||||
|
|
||||||
if parser.token.kind == TokenKind::Eof {
|
|
||||||
trailing_comma = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
if !arg_vec.is_empty() && arg_vec.iter().all(MacroArg::is_item) {
|
if !arg_vec.is_empty() && arg_vec.iter().all(MacroArg::is_item) {
|
||||||
return rewrite_macro_with_items(
|
return rewrite_macro_with_items(
|
||||||
|
@ -1179,11 +1060,10 @@ pub(crate) fn convert_try_mac(
|
||||||
let path = &pprust::path_to_string(&mac.path);
|
let path = &pprust::path_to_string(&mac.path);
|
||||||
if path == "try" || path == "r#try" {
|
if path == "try" || path == "r#try" {
|
||||||
let ts = mac.args.inner_tokens();
|
let ts = mac.args.inner_tokens();
|
||||||
let mut parser = build_parser(context, ts.trees());
|
|
||||||
|
|
||||||
Some(ast::Expr {
|
Some(ast::Expr {
|
||||||
id: ast::NodeId::root(), // dummy value
|
id: ast::NodeId::root(), // dummy value
|
||||||
kind: ast::ExprKind::Try(parser.parse_expr().ok()?),
|
kind: ast::ExprKind::Try(parse_expr(context, ts)?),
|
||||||
span: mac.span(), // incorrect span, but shouldn't matter too much
|
span: mac.span(), // incorrect span, but shouldn't matter too much
|
||||||
attrs: ast::AttrVec::new(),
|
attrs: ast::AttrVec::new(),
|
||||||
tokens: None,
|
tokens: None,
|
||||||
|
@ -1414,10 +1294,9 @@ impl MacroBranch {
|
||||||
fn format_lazy_static(
|
fn format_lazy_static(
|
||||||
context: &RewriteContext<'_>,
|
context: &RewriteContext<'_>,
|
||||||
shape: Shape,
|
shape: Shape,
|
||||||
ts: &TokenStream,
|
ts: TokenStream,
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
let mut result = String::with_capacity(1024);
|
let mut result = String::with_capacity(1024);
|
||||||
let mut parser = build_parser(context, ts.trees());
|
|
||||||
let nested_shape = shape
|
let nested_shape = shape
|
||||||
.block_indent(context.config.tab_spaces())
|
.block_indent(context.config.tab_spaces())
|
||||||
.with_max_width(context.config);
|
.with_max_width(context.config);
|
||||||
|
@ -1425,42 +1304,11 @@ fn format_lazy_static(
|
||||||
result.push_str("lazy_static! {");
|
result.push_str("lazy_static! {");
|
||||||
result.push_str(&nested_shape.indent.to_string_with_newline(context.config));
|
result.push_str(&nested_shape.indent.to_string_with_newline(context.config));
|
||||||
|
|
||||||
macro_rules! parse_or {
|
let parsed_elems = parse_lazy_static(context, ts)?;
|
||||||
($method:ident $(,)* $($arg:expr),* $(,)*) => {
|
let last = parsed_elems.len() - 1;
|
||||||
match parser.$method($($arg,)*) {
|
for (i, (vis, id, ty, expr)) in parsed_elems.iter().enumerate() {
|
||||||
Ok(val) => {
|
|
||||||
if parser.sess.span_diagnostic.has_errors() {
|
|
||||||
parser.sess.span_diagnostic.reset_err_count();
|
|
||||||
return None;
|
|
||||||
} else {
|
|
||||||
val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(mut err) => {
|
|
||||||
err.cancel();
|
|
||||||
parser.sess.span_diagnostic.reset_err_count();
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while parser.token.kind != TokenKind::Eof {
|
|
||||||
// Parse a `lazy_static!` item.
|
|
||||||
let vis = crate::utils::format_visibility(
|
|
||||||
context,
|
|
||||||
&parse_or!(parse_visibility, rustc_parse::parser::FollowedByType::No),
|
|
||||||
);
|
|
||||||
parser.eat_keyword(kw::Static);
|
|
||||||
parser.eat_keyword(kw::Ref);
|
|
||||||
let id = parse_or!(parse_ident);
|
|
||||||
parser.eat(&TokenKind::Colon);
|
|
||||||
let ty = parse_or!(parse_ty);
|
|
||||||
parser.eat(&TokenKind::Eq);
|
|
||||||
let expr = parse_or!(parse_expr);
|
|
||||||
parser.eat(&TokenKind::Semi);
|
|
||||||
|
|
||||||
// Rewrite as a static item.
|
// Rewrite as a static item.
|
||||||
|
let vis = crate::utils::format_visibility(context, vis);
|
||||||
let mut stmt = String::with_capacity(128);
|
let mut stmt = String::with_capacity(128);
|
||||||
stmt.push_str(&format!(
|
stmt.push_str(&format!(
|
||||||
"{}static ref {}: {} =",
|
"{}static ref {}: {} =",
|
||||||
|
@ -1476,7 +1324,7 @@ fn format_lazy_static(
|
||||||
nested_shape.sub_width(1)?,
|
nested_shape.sub_width(1)?,
|
||||||
)?);
|
)?);
|
||||||
result.push(';');
|
result.push(';');
|
||||||
if parser.token.kind != TokenKind::Eof {
|
if i != last {
|
||||||
result.push_str(&nested_shape.indent.to_string_with_newline(context.config));
|
result.push_str(&nested_shape.indent.to_string_with_newline(context.config));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1528,65 +1376,3 @@ fn rewrite_macro_with_items(
|
||||||
result.push_str(trailing_semicolon);
|
result.push_str(trailing_semicolon);
|
||||||
Some(result)
|
Some(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
const RUST_KW: [Symbol; 59] = [
|
|
||||||
kw::PathRoot,
|
|
||||||
kw::DollarCrate,
|
|
||||||
kw::Underscore,
|
|
||||||
kw::As,
|
|
||||||
kw::Box,
|
|
||||||
kw::Break,
|
|
||||||
kw::Const,
|
|
||||||
kw::Continue,
|
|
||||||
kw::Crate,
|
|
||||||
kw::Else,
|
|
||||||
kw::Enum,
|
|
||||||
kw::Extern,
|
|
||||||
kw::False,
|
|
||||||
kw::Fn,
|
|
||||||
kw::For,
|
|
||||||
kw::If,
|
|
||||||
kw::Impl,
|
|
||||||
kw::In,
|
|
||||||
kw::Let,
|
|
||||||
kw::Loop,
|
|
||||||
kw::Match,
|
|
||||||
kw::Mod,
|
|
||||||
kw::Move,
|
|
||||||
kw::Mut,
|
|
||||||
kw::Pub,
|
|
||||||
kw::Ref,
|
|
||||||
kw::Return,
|
|
||||||
kw::SelfLower,
|
|
||||||
kw::SelfUpper,
|
|
||||||
kw::Static,
|
|
||||||
kw::Struct,
|
|
||||||
kw::Super,
|
|
||||||
kw::Trait,
|
|
||||||
kw::True,
|
|
||||||
kw::Type,
|
|
||||||
kw::Unsafe,
|
|
||||||
kw::Use,
|
|
||||||
kw::Where,
|
|
||||||
kw::While,
|
|
||||||
kw::Abstract,
|
|
||||||
kw::Become,
|
|
||||||
kw::Do,
|
|
||||||
kw::Final,
|
|
||||||
kw::Macro,
|
|
||||||
kw::Override,
|
|
||||||
kw::Priv,
|
|
||||||
kw::Typeof,
|
|
||||||
kw::Unsized,
|
|
||||||
kw::Virtual,
|
|
||||||
kw::Yield,
|
|
||||||
kw::Dyn,
|
|
||||||
kw::Async,
|
|
||||||
kw::Try,
|
|
||||||
kw::UnderscoreLifetime,
|
|
||||||
kw::StaticLifetime,
|
|
||||||
kw::Auto,
|
|
||||||
kw::Catch,
|
|
||||||
kw::Default,
|
|
||||||
kw::Union,
|
|
||||||
];
|
|
||||||
|
|
|
@ -322,7 +322,11 @@ fn flatten_arm_body<'a>(
|
||||||
if let Some(block) = block_can_be_flattened(context, body) {
|
if let Some(block) = block_can_be_flattened(context, body) {
|
||||||
if let ast::StmtKind::Expr(ref expr) = block.stmts[0].kind {
|
if let ast::StmtKind::Expr(ref expr) = block.stmts[0].kind {
|
||||||
if let ast::ExprKind::Block(..) = expr.kind {
|
if let ast::ExprKind::Block(..) = expr.kind {
|
||||||
flatten_arm_body(context, expr, None)
|
if expr.attrs.is_empty() {
|
||||||
|
flatten_arm_body(context, expr, None)
|
||||||
|
} else {
|
||||||
|
(true, body)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let cond_becomes_muti_line = opt_shape
|
let cond_becomes_muti_line = opt_shape
|
||||||
.and_then(|shape| rewrite_cond(context, expr, shape))
|
.and_then(|shape| rewrite_cond(context, expr, shape))
|
||||||
|
|
|
@ -12,10 +12,10 @@ use thiserror::Error;
|
||||||
use crate::attr::MetaVisitor;
|
use crate::attr::MetaVisitor;
|
||||||
use crate::config::FileName;
|
use crate::config::FileName;
|
||||||
use crate::items::is_mod_decl;
|
use crate::items::is_mod_decl;
|
||||||
use crate::syntux::parser::{
|
use crate::parse::parser::{
|
||||||
Directory, DirectoryOwnership, ModError, ModulePathSuccess, Parser, ParserError,
|
Directory, DirectoryOwnership, ModError, ModulePathSuccess, Parser, ParserError,
|
||||||
};
|
};
|
||||||
use crate::syntux::session::ParseSess;
|
use crate::parse::session::ParseSess;
|
||||||
use crate::utils::{contains_skip, mk_sp};
|
use crate::utils::{contains_skip, mk_sp};
|
||||||
|
|
||||||
mod visitor;
|
mod visitor;
|
||||||
|
|
|
@ -3,8 +3,8 @@ use rustc_ast::visit::Visitor;
|
||||||
use rustc_span::Symbol;
|
use rustc_span::Symbol;
|
||||||
|
|
||||||
use crate::attr::MetaVisitor;
|
use crate::attr::MetaVisitor;
|
||||||
use crate::syntux::parser::Parser;
|
use crate::parse::macros::cfg_if::parse_cfg_if;
|
||||||
use crate::syntux::session::ParseSess;
|
use crate::parse::session::ParseSess;
|
||||||
|
|
||||||
pub(crate) struct ModItem {
|
pub(crate) struct ModItem {
|
||||||
pub(crate) item: ast::Item,
|
pub(crate) item: ast::Item,
|
||||||
|
@ -62,7 +62,7 @@ impl<'a, 'ast: 'a> CfgIfVisitor<'a> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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());
|
||||||
|
|
||||||
|
|
11
src/tools/rustfmt/src/parse/macros/asm.rs
Normal file
11
src/tools/rustfmt/src/parse/macros/asm.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
use rustc_ast::ast;
|
||||||
|
use rustc_builtin_macros::asm::{parse_asm_args, AsmArgs};
|
||||||
|
|
||||||
|
use crate::rewrite::RewriteContext;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub(crate) fn parse_asm(context: &RewriteContext<'_>, mac: &ast::MacCall) -> Option<AsmArgs> {
|
||||||
|
let ts = mac.args.inner_tokens();
|
||||||
|
let mut parser = super::build_parser(context, ts);
|
||||||
|
parse_asm_args(&mut parser, context.parse_sess.inner(), mac.span(), false).ok()
|
||||||
|
}
|
89
src/tools/rustfmt/src/parse/macros/cfg_if.rs
Normal file
89
src/tools/rustfmt/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)
|
||||||
|
}
|
50
src/tools/rustfmt/src/parse/macros/lazy_static.rs
Normal file
50
src/tools/rustfmt/src/parse/macros/lazy_static.rs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
use rustc_ast::ast;
|
||||||
|
use rustc_ast::ptr::P;
|
||||||
|
use rustc_ast::token::TokenKind;
|
||||||
|
use rustc_ast::tokenstream::TokenStream;
|
||||||
|
use rustc_span::symbol::{self, kw};
|
||||||
|
|
||||||
|
use crate::rewrite::RewriteContext;
|
||||||
|
|
||||||
|
pub(crate) fn parse_lazy_static(
|
||||||
|
context: &RewriteContext<'_>,
|
||||||
|
ts: TokenStream,
|
||||||
|
) -> Option<Vec<(ast::Visibility, symbol::Ident, P<ast::Ty>, P<ast::Expr>)>> {
|
||||||
|
let mut result = vec![];
|
||||||
|
let mut parser = super::build_parser(context, ts);
|
||||||
|
macro_rules! parse_or {
|
||||||
|
($method:ident $(,)* $($arg:expr),* $(,)*) => {
|
||||||
|
match parser.$method($($arg,)*) {
|
||||||
|
Ok(val) => {
|
||||||
|
if parser.sess.span_diagnostic.has_errors() {
|
||||||
|
parser.sess.span_diagnostic.reset_err_count();
|
||||||
|
return None;
|
||||||
|
} else {
|
||||||
|
val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(mut err) => {
|
||||||
|
err.cancel();
|
||||||
|
parser.sess.span_diagnostic.reset_err_count();
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while parser.token.kind != TokenKind::Eof {
|
||||||
|
// Parse a `lazy_static!` item.
|
||||||
|
let vis = parse_or!(parse_visibility, rustc_parse::parser::FollowedByType::No);
|
||||||
|
parser.eat_keyword(kw::Static);
|
||||||
|
parser.eat_keyword(kw::Ref);
|
||||||
|
let id = parse_or!(parse_ident);
|
||||||
|
parser.eat(&TokenKind::Colon);
|
||||||
|
let ty = parse_or!(parse_ty);
|
||||||
|
parser.eat(&TokenKind::Eq);
|
||||||
|
let expr = parse_or!(parse_expr);
|
||||||
|
parser.eat(&TokenKind::Semi);
|
||||||
|
result.push((vis, id, ty, expr));
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(result)
|
||||||
|
}
|
231
src/tools/rustfmt/src/parse/macros/mod.rs
Normal file
231
src/tools/rustfmt/src/parse/macros/mod.rs
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
use rustc_ast::token::{DelimToken, TokenKind};
|
||||||
|
use rustc_ast::tokenstream::TokenStream;
|
||||||
|
use rustc_ast::{ast, ptr};
|
||||||
|
use rustc_parse::parser::{ForceCollect, Parser};
|
||||||
|
use rustc_parse::{stream_to_parser, MACRO_ARGUMENTS};
|
||||||
|
use rustc_session::parse::ParseSess;
|
||||||
|
use rustc_span::symbol::{self, kw};
|
||||||
|
use rustc_span::Symbol;
|
||||||
|
|
||||||
|
use crate::macros::MacroArg;
|
||||||
|
use crate::rewrite::RewriteContext;
|
||||||
|
|
||||||
|
pub(crate) mod asm;
|
||||||
|
pub(crate) mod cfg_if;
|
||||||
|
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> {
|
||||||
|
build_stream_parser(context.parse_sess.inner(), tokens)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
|
||||||
|
macro_rules! parse_macro_arg {
|
||||||
|
($macro_arg:ident, $parser:expr, $f:expr) => {
|
||||||
|
let mut cloned_parser = (*parser).clone();
|
||||||
|
match $parser(&mut cloned_parser) {
|
||||||
|
Ok(x) => {
|
||||||
|
if parser.sess.span_diagnostic.has_errors() {
|
||||||
|
parser.sess.span_diagnostic.reset_err_count();
|
||||||
|
} else {
|
||||||
|
// Parsing succeeded.
|
||||||
|
*parser = cloned_parser;
|
||||||
|
return Some(MacroArg::$macro_arg($f(x)?));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(mut e) => {
|
||||||
|
e.cancel();
|
||||||
|
parser.sess.span_diagnostic.reset_err_count();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_macro_arg!(
|
||||||
|
Expr,
|
||||||
|
|parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_expr(),
|
||||||
|
|x: ptr::P<ast::Expr>| Some(x)
|
||||||
|
);
|
||||||
|
parse_macro_arg!(
|
||||||
|
Ty,
|
||||||
|
|parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_ty(),
|
||||||
|
|x: ptr::P<ast::Ty>| Some(x)
|
||||||
|
);
|
||||||
|
parse_macro_arg!(
|
||||||
|
Pat,
|
||||||
|
|parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_pat_no_top_alt(None),
|
||||||
|
|x: ptr::P<ast::Pat>| Some(x)
|
||||||
|
);
|
||||||
|
// `parse_item` returns `Option<ptr::P<ast::Item>>`.
|
||||||
|
parse_macro_arg!(
|
||||||
|
Item,
|
||||||
|
|parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_item(ForceCollect::No),
|
||||||
|
|x: Option<ptr::P<ast::Item>>| x
|
||||||
|
);
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct ParsedMacroArgs {
|
||||||
|
pub(crate) vec_with_semi: bool,
|
||||||
|
pub(crate) trailing_comma: bool,
|
||||||
|
pub(crate) args: Vec<MacroArg>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
|
||||||
|
for &keyword in RUST_KW.iter() {
|
||||||
|
if parser.token.is_keyword(keyword)
|
||||||
|
&& parser.look_ahead(1, |t| {
|
||||||
|
t.kind == TokenKind::Eof
|
||||||
|
|| t.kind == TokenKind::Comma
|
||||||
|
|| t.kind == TokenKind::CloseDelim(DelimToken::NoDelim)
|
||||||
|
})
|
||||||
|
{
|
||||||
|
parser.bump();
|
||||||
|
return Some(MacroArg::Keyword(
|
||||||
|
symbol::Ident::with_dummy_span(keyword),
|
||||||
|
parser.prev_token.span,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn parse_macro_args(
|
||||||
|
context: &RewriteContext<'_>,
|
||||||
|
tokens: TokenStream,
|
||||||
|
style: DelimToken,
|
||||||
|
forced_bracket: bool,
|
||||||
|
) -> Option<ParsedMacroArgs> {
|
||||||
|
let mut parser = build_parser(context, tokens);
|
||||||
|
let mut args = Vec::new();
|
||||||
|
let mut vec_with_semi = false;
|
||||||
|
let mut trailing_comma = false;
|
||||||
|
|
||||||
|
if DelimToken::Brace != style {
|
||||||
|
loop {
|
||||||
|
if let Some(arg) = check_keyword(&mut parser) {
|
||||||
|
args.push(arg);
|
||||||
|
} else if let Some(arg) = parse_macro_arg(&mut parser) {
|
||||||
|
args.push(arg);
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
match parser.token.kind {
|
||||||
|
TokenKind::Eof => break,
|
||||||
|
TokenKind::Comma => (),
|
||||||
|
TokenKind::Semi => {
|
||||||
|
// Try to parse `vec![expr; expr]`
|
||||||
|
if forced_bracket {
|
||||||
|
parser.bump();
|
||||||
|
if parser.token.kind != TokenKind::Eof {
|
||||||
|
match parse_macro_arg(&mut parser) {
|
||||||
|
Some(arg) => {
|
||||||
|
args.push(arg);
|
||||||
|
parser.bump();
|
||||||
|
if parser.token.kind == TokenKind::Eof && args.len() == 2 {
|
||||||
|
vec_with_semi = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
_ if args.last().map_or(false, MacroArg::is_item) => continue,
|
||||||
|
_ => return None,
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.bump();
|
||||||
|
|
||||||
|
if parser.token.kind == TokenKind::Eof {
|
||||||
|
trailing_comma = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(ParsedMacroArgs {
|
||||||
|
vec_with_semi,
|
||||||
|
trailing_comma,
|
||||||
|
args,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn parse_expr(
|
||||||
|
context: &RewriteContext<'_>,
|
||||||
|
tokens: TokenStream,
|
||||||
|
) -> Option<ptr::P<ast::Expr>> {
|
||||||
|
let mut parser = build_parser(context, tokens);
|
||||||
|
parser.parse_expr().ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
const RUST_KW: [Symbol; 59] = [
|
||||||
|
kw::PathRoot,
|
||||||
|
kw::DollarCrate,
|
||||||
|
kw::Underscore,
|
||||||
|
kw::As,
|
||||||
|
kw::Box,
|
||||||
|
kw::Break,
|
||||||
|
kw::Const,
|
||||||
|
kw::Continue,
|
||||||
|
kw::Crate,
|
||||||
|
kw::Else,
|
||||||
|
kw::Enum,
|
||||||
|
kw::Extern,
|
||||||
|
kw::False,
|
||||||
|
kw::Fn,
|
||||||
|
kw::For,
|
||||||
|
kw::If,
|
||||||
|
kw::Impl,
|
||||||
|
kw::In,
|
||||||
|
kw::Let,
|
||||||
|
kw::Loop,
|
||||||
|
kw::Match,
|
||||||
|
kw::Mod,
|
||||||
|
kw::Move,
|
||||||
|
kw::Mut,
|
||||||
|
kw::Pub,
|
||||||
|
kw::Ref,
|
||||||
|
kw::Return,
|
||||||
|
kw::SelfLower,
|
||||||
|
kw::SelfUpper,
|
||||||
|
kw::Static,
|
||||||
|
kw::Struct,
|
||||||
|
kw::Super,
|
||||||
|
kw::Trait,
|
||||||
|
kw::True,
|
||||||
|
kw::Type,
|
||||||
|
kw::Unsafe,
|
||||||
|
kw::Use,
|
||||||
|
kw::Where,
|
||||||
|
kw::While,
|
||||||
|
kw::Abstract,
|
||||||
|
kw::Become,
|
||||||
|
kw::Do,
|
||||||
|
kw::Final,
|
||||||
|
kw::Macro,
|
||||||
|
kw::Override,
|
||||||
|
kw::Priv,
|
||||||
|
kw::Typeof,
|
||||||
|
kw::Unsized,
|
||||||
|
kw::Virtual,
|
||||||
|
kw::Yield,
|
||||||
|
kw::Dyn,
|
||||||
|
kw::Async,
|
||||||
|
kw::Try,
|
||||||
|
kw::UnderscoreLifetime,
|
||||||
|
kw::StaticLifetime,
|
||||||
|
kw::Auto,
|
||||||
|
kw::Catch,
|
||||||
|
kw::Default,
|
||||||
|
kw::Union,
|
||||||
|
];
|
3
src/tools/rustfmt/src/parse/mod.rs
Normal file
3
src/tools/rustfmt/src/parse/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
pub(crate) mod macros;
|
||||||
|
pub(crate) mod parser;
|
||||||
|
pub(crate) mod session;
|
|
@ -1,17 +1,14 @@
|
||||||
use std::panic::{catch_unwind, AssertUnwindSafe};
|
use std::panic::{catch_unwind, AssertUnwindSafe};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use rustc_ast::token::{DelimToken, TokenKind};
|
use rustc_ast::token::TokenKind;
|
||||||
use rustc_ast::{ast, ptr};
|
use rustc_ast::{ast, ptr};
|
||||||
use rustc_errors::Diagnostic;
|
use rustc_errors::Diagnostic;
|
||||||
use rustc_parse::{
|
use rustc_parse::{new_parser_from_file, parser::Parser as RawParser};
|
||||||
new_parser_from_file,
|
use rustc_span::{sym, Span};
|
||||||
parser::{ForceCollect, Parser as RawParser},
|
|
||||||
};
|
|
||||||
use rustc_span::{sym, symbol::kw, Span};
|
|
||||||
|
|
||||||
use crate::attr::first_attr_value_str_by_name;
|
use crate::attr::first_attr_value_str_by_name;
|
||||||
use crate::syntux::session::ParseSess;
|
use crate::parse::session::ParseSess;
|
||||||
use crate::Input;
|
use crate::Input;
|
||||||
|
|
||||||
pub(crate) type DirectoryOwnership = rustc_expand::module::DirOwnership;
|
pub(crate) type DirectoryOwnership = rustc_expand::module::DirOwnership;
|
||||||
|
@ -175,84 +172,4 @@ impl<'a> Parser<'a> {
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -222,7 +222,7 @@ impl ParseSess {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Methods that should be restricted within the syntux module.
|
// Methods that should be restricted within the parse module.
|
||||||
impl ParseSess {
|
impl ParseSess {
|
||||||
pub(super) fn emit_diagnostics(&self, diagnostics: Vec<Diagnostic>) {
|
pub(super) fn emit_diagnostics(&self, diagnostics: Vec<Diagnostic>) {
|
||||||
for diagnostic in diagnostics {
|
for diagnostic in diagnostics {
|
|
@ -318,10 +318,12 @@ fn rewrite_struct_pat(
|
||||||
let mut fields_str = write_list(&item_vec, &fmt)?;
|
let mut fields_str = write_list(&item_vec, &fmt)?;
|
||||||
let one_line_width = h_shape.map_or(0, |shape| shape.width);
|
let one_line_width = h_shape.map_or(0, |shape| shape.width);
|
||||||
|
|
||||||
|
let has_trailing_comma = fmt.needs_trailing_separator();
|
||||||
|
|
||||||
if ellipsis {
|
if ellipsis {
|
||||||
if fields_str.contains('\n') || fields_str.len() > one_line_width {
|
if fields_str.contains('\n') || fields_str.len() > one_line_width {
|
||||||
// Add a missing trailing comma.
|
// Add a missing trailing comma.
|
||||||
if context.config.trailing_comma() == SeparatorTactic::Never {
|
if !has_trailing_comma {
|
||||||
fields_str.push(',');
|
fields_str.push(',');
|
||||||
}
|
}
|
||||||
fields_str.push('\n');
|
fields_str.push('\n');
|
||||||
|
@ -329,8 +331,7 @@ fn rewrite_struct_pat(
|
||||||
} else {
|
} else {
|
||||||
if !fields_str.is_empty() {
|
if !fields_str.is_empty() {
|
||||||
// there are preceding struct fields being matched on
|
// there are preceding struct fields being matched on
|
||||||
if tactic == DefinitiveListTactic::Vertical {
|
if has_trailing_comma {
|
||||||
// if the tactic is Vertical, write_list already added a trailing ,
|
|
||||||
fields_str.push(' ');
|
fields_str.push(' ');
|
||||||
} else {
|
} else {
|
||||||
fields_str.push_str(", ");
|
fields_str.push_str(", ");
|
||||||
|
|
|
@ -7,9 +7,9 @@ use rustc_ast::ptr;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
use crate::config::{Config, IndentStyle};
|
use crate::config::{Config, IndentStyle};
|
||||||
|
use crate::parse::session::ParseSess;
|
||||||
use crate::shape::Shape;
|
use crate::shape::Shape;
|
||||||
use crate::skip::SkipContext;
|
use crate::skip::SkipContext;
|
||||||
use crate::syntux::session::ParseSess;
|
|
||||||
use crate::visitor::SnippetProvider;
|
use crate::visitor::SnippetProvider;
|
||||||
use crate::FormatReport;
|
use crate::FormatReport;
|
||||||
|
|
||||||
|
|
|
@ -6,20 +6,20 @@ use std::io::Write;
|
||||||
use crate::config::{Color, Config, Verbosity};
|
use crate::config::{Color, Config, Verbosity};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum DiffLine {
|
pub(crate) enum DiffLine {
|
||||||
Context(String),
|
Context(String),
|
||||||
Expected(String),
|
Expected(String),
|
||||||
Resulting(String),
|
Resulting(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Mismatch {
|
pub(crate) struct Mismatch {
|
||||||
/// The line number in the formatted version.
|
/// The line number in the formatted version.
|
||||||
pub line_number: u32,
|
pub(crate) line_number: u32,
|
||||||
/// The line number in the original version.
|
/// The line number in the original version.
|
||||||
pub line_number_orig: u32,
|
pub(crate) line_number_orig: u32,
|
||||||
/// The set of lines (context and old/new) in the mismatch.
|
/// The set of lines (context and old/new) in the mismatch.
|
||||||
pub lines: Vec<DiffLine>,
|
pub(crate) lines: Vec<DiffLine>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mismatch {
|
impl Mismatch {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::path::Path;
|
||||||
|
|
||||||
use crate::config::FileName;
|
use crate::config::FileName;
|
||||||
use crate::emitter::{self, Emitter};
|
use crate::emitter::{self, Emitter};
|
||||||
use crate::syntux::session::ParseSess;
|
use crate::parse::session::ParseSess;
|
||||||
use crate::NewlineStyle;
|
use crate::NewlineStyle;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -110,14 +110,7 @@ impl ConfigCodeBlock {
|
||||||
assert!(self.code_block.is_some() && self.code_block_start.is_some());
|
assert!(self.code_block.is_some() && self.code_block_start.is_some());
|
||||||
|
|
||||||
// See if code block begins with #![rustfmt::skip].
|
// See if code block begins with #![rustfmt::skip].
|
||||||
let fmt_skip = self
|
let fmt_skip = self.fmt_skip();
|
||||||
.code_block
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.lines()
|
|
||||||
.nth(0)
|
|
||||||
.unwrap_or("")
|
|
||||||
== "#![rustfmt::skip]";
|
|
||||||
|
|
||||||
if self.config_name.is_none() && !fmt_skip {
|
if self.config_name.is_none() && !fmt_skip {
|
||||||
write_message(&format!(
|
write_message(&format!(
|
||||||
|
@ -138,6 +131,17 @@ impl ConfigCodeBlock {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// True if the code block starts with #![rustfmt::skip]
|
||||||
|
fn fmt_skip(&self) -> bool {
|
||||||
|
self.code_block
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.lines()
|
||||||
|
.nth(0)
|
||||||
|
.unwrap_or("")
|
||||||
|
== "#![rustfmt::skip]"
|
||||||
|
}
|
||||||
|
|
||||||
fn has_parsing_errors<T: Write>(&self, session: &Session<'_, T>) -> bool {
|
fn has_parsing_errors<T: Write>(&self, session: &Session<'_, T>) -> bool {
|
||||||
if session.has_parsing_errors() {
|
if session.has_parsing_errors() {
|
||||||
write_message(&format!(
|
write_message(&format!(
|
||||||
|
@ -251,6 +255,7 @@ fn configuration_snippet_tests() {
|
||||||
let blocks = get_code_blocks();
|
let blocks = get_code_blocks();
|
||||||
let failures = blocks
|
let failures = blocks
|
||||||
.iter()
|
.iter()
|
||||||
|
.filter(|block| !block.fmt_skip())
|
||||||
.map(ConfigCodeBlock::formatted_is_idempotent)
|
.map(ConfigCodeBlock::formatted_is_idempotent)
|
||||||
.fold(0, |acc, r| acc + (!r as u32));
|
.fold(0, |acc, r| acc + (!r as u32));
|
||||||
|
|
||||||
|
|
|
@ -41,3 +41,12 @@ fn out_of_line_nested_inline_within_out_of_line() {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn skip_out_of_line_nested_inline_within_out_of_line() {
|
||||||
|
// See also https://github.com/rust-lang/rustfmt/issues/5065
|
||||||
|
verify_mod_resolution(
|
||||||
|
"tests/mod-resolver/skip-files-issue-5065/main.rs",
|
||||||
|
&["tests/mod-resolver/skip-files-issue-5065/one.rs"],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -16,13 +16,13 @@ use crate::items::{
|
||||||
};
|
};
|
||||||
use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition};
|
use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition};
|
||||||
use crate::modules::Module;
|
use crate::modules::Module;
|
||||||
|
use crate::parse::session::ParseSess;
|
||||||
use crate::rewrite::{Rewrite, RewriteContext};
|
use crate::rewrite::{Rewrite, RewriteContext};
|
||||||
use crate::shape::{Indent, Shape};
|
use crate::shape::{Indent, Shape};
|
||||||
use crate::skip::{is_skip_attr, SkipContext};
|
use crate::skip::{is_skip_attr, SkipContext};
|
||||||
use crate::source_map::{LineRangeUtils, SpanUtils};
|
use crate::source_map::{LineRangeUtils, SpanUtils};
|
||||||
use crate::spanned::Spanned;
|
use crate::spanned::Spanned;
|
||||||
use crate::stmt::Stmt;
|
use crate::stmt::Stmt;
|
||||||
use crate::syntux::session::ParseSess;
|
|
||||||
use crate::utils::{
|
use crate::utils::{
|
||||||
self, contains_skip, count_newlines, depr_skip_annotation, format_unsafety, inner_attributes,
|
self, contains_skip, count_newlines, depr_skip_annotation, format_unsafety, inner_attributes,
|
||||||
last_line_width, mk_sp, ptr_vec_to_ref_vec, rewrite_ident, starts_with_newline, stmt_expr,
|
last_line_width, mk_sp, ptr_vec_to_ref_vec, rewrite_ident, starts_with_newline, stmt_expr,
|
||||||
|
@ -552,7 +552,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
|
||||||
_ => visit::FnCtxt::Foreign,
|
_ => visit::FnCtxt::Foreign,
|
||||||
};
|
};
|
||||||
self.visit_fn(
|
self.visit_fn(
|
||||||
visit::FnKind::Fn(fn_ctxt, item.ident, &sig, &item.vis, Some(body)),
|
visit::FnKind::Fn(fn_ctxt, item.ident, sig, &item.vis, Some(body)),
|
||||||
generics,
|
generics,
|
||||||
&sig.decl,
|
&sig.decl,
|
||||||
item.span,
|
item.span,
|
||||||
|
@ -562,14 +562,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
|
||||||
} else {
|
} else {
|
||||||
let indent = self.block_indent;
|
let indent = self.block_indent;
|
||||||
let rewrite = self.rewrite_required_fn(
|
let rewrite = self.rewrite_required_fn(
|
||||||
indent, item.ident, &sig, &item.vis, generics, item.span,
|
indent, item.ident, sig, &item.vis, generics, item.span,
|
||||||
);
|
);
|
||||||
self.push_rewrite(item.span, rewrite);
|
self.push_rewrite(item.span, rewrite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ItemKind::TyAlias(ref ty_alias) => {
|
ast::ItemKind::TyAlias(ref ty_alias) => {
|
||||||
use ItemVisitorKind::Item;
|
use ItemVisitorKind::Item;
|
||||||
self.visit_ty_alias_kind(ty_alias, &Item(&item), item.span);
|
self.visit_ty_alias_kind(ty_alias, &Item(item), item.span);
|
||||||
}
|
}
|
||||||
ast::ItemKind::GlobalAsm(..) => {
|
ast::ItemKind::GlobalAsm(..) => {
|
||||||
let snippet = Some(self.snippet(item.span).to_owned());
|
let snippet = Some(self.snippet(item.span).to_owned());
|
||||||
|
@ -619,17 +619,17 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
|
||||||
skip_out_of_file_lines_range_visitor!(self, ai.span);
|
skip_out_of_file_lines_range_visitor!(self, ai.span);
|
||||||
|
|
||||||
if self.visit_attrs(&ai.attrs, ast::AttrStyle::Outer) {
|
if self.visit_attrs(&ai.attrs, ast::AttrStyle::Outer) {
|
||||||
self.push_skipped_with_span(&ai.attrs.as_slice(), skip_span, skip_span);
|
self.push_skipped_with_span(ai.attrs.as_slice(), skip_span, skip_span);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(calebcartwright): consider enabling box_patterns feature gate
|
// TODO(calebcartwright): consider enabling box_patterns feature gate
|
||||||
match (&ai.kind, visitor_kind) {
|
match (&ai.kind, visitor_kind) {
|
||||||
(ast::AssocItemKind::Const(..), AssocTraitItem(_)) => {
|
(ast::AssocItemKind::Const(..), AssocTraitItem(_)) => {
|
||||||
self.visit_static(&StaticParts::from_trait_item(&ai))
|
self.visit_static(&StaticParts::from_trait_item(ai))
|
||||||
}
|
}
|
||||||
(ast::AssocItemKind::Const(..), AssocImplItem(_)) => {
|
(ast::AssocItemKind::Const(..), AssocImplItem(_)) => {
|
||||||
self.visit_static(&StaticParts::from_impl_item(&ai))
|
self.visit_static(&StaticParts::from_impl_item(ai))
|
||||||
}
|
}
|
||||||
(ast::AssocItemKind::Fn(ref fn_kind), _) => {
|
(ast::AssocItemKind::Fn(ref fn_kind), _) => {
|
||||||
let ast::Fn {
|
let ast::Fn {
|
||||||
|
@ -948,12 +948,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
|
||||||
|
|
||||||
pub(crate) fn format_separate_mod(&mut self, m: &Module<'_>, end_pos: BytePos) {
|
pub(crate) fn format_separate_mod(&mut self, m: &Module<'_>, end_pos: BytePos) {
|
||||||
self.block_indent = Indent::empty();
|
self.block_indent = Indent::empty();
|
||||||
if self.visit_attrs(m.attrs(), ast::AttrStyle::Inner) {
|
let skipped = self.visit_attrs(m.attrs(), ast::AttrStyle::Inner);
|
||||||
self.push_skipped_with_span(m.attrs(), m.span, m.span);
|
assert!(
|
||||||
} else {
|
!skipped,
|
||||||
self.walk_mod_items(&m.items);
|
"Skipping module must be handled before reaching this line."
|
||||||
self.format_missing_with_indent(end_pos);
|
);
|
||||||
}
|
self.walk_mod_items(&m.items);
|
||||||
|
self.format_missing_with_indent(end_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn skip_empty_lines(&mut self, end_pos: BytePos) {
|
pub(crate) fn skip_empty_lines(&mut self, end_pos: BytePos) {
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
#![rustfmt::skip]
|
||||||
|
|
||||||
|
mod bar {
|
||||||
|
|
||||||
|
mod baz;}
|
|
@ -0,0 +1 @@
|
||||||
|
fn baz() { }
|
|
@ -0,0 +1,9 @@
|
||||||
|
#![rustfmt::skip]
|
||||||
|
|
||||||
|
mod foo;
|
||||||
|
mod one;
|
||||||
|
|
||||||
|
fn main() {println!("Hello, world!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// trailing commet
|
|
@ -0,0 +1 @@
|
||||||
|
struct One { value: String }
|
|
@ -32,4 +32,20 @@ fn baz() {
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
spawn(
|
||||||
|
a,
|
||||||
|
static async || {
|
||||||
|
action();
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
spawn(
|
||||||
|
a,
|
||||||
|
static async move || {
|
||||||
|
action();
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -568,3 +568,22 @@ fn issue_3774() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #4109
|
||||||
|
fn issue_4109() {
|
||||||
|
match () {
|
||||||
|
_ => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
{
|
||||||
|
println!("Foo");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match () {
|
||||||
|
_ => {
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -22,4 +22,14 @@ fn baz() {
|
||||||
action();
|
action();
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|
||||||
|
spawn(a, static async || {
|
||||||
|
action();
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
|
||||||
|
spawn(a, static async move || {
|
||||||
|
action();
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
// rustfmt-trailing_comma: Always
|
||||||
|
// rustfmt-struct_lit_single_line: false
|
||||||
|
// rustfmt-struct_lit_width: 0
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let Foo {
|
||||||
|
a,
|
||||||
|
..
|
||||||
|
} = b;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
// rustfmt-trailing_comma: Never
|
||||||
|
// rustfmt-struct_lit_single_line: false
|
||||||
|
// rustfmt-struct_lit_width: 0
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let Foo {
|
||||||
|
a,
|
||||||
|
..
|
||||||
|
} = b;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
// rustfmt-trailing_comma: Always
|
||||||
|
// rustfmt-struct_lit_single_line: false
|
||||||
|
|
||||||
|
// There is an issue with how this is formatted.
|
||||||
|
// formatting should look like ./multi_line_struct_trailing_comma_always_struct_lit_width_0.rs
|
||||||
|
fn main() {
|
||||||
|
let Foo {
|
||||||
|
a, ..
|
||||||
|
} = b;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
// rustfmt-trailing_comma: Never
|
||||||
|
// rustfmt-struct_lit_single_line: false
|
||||||
|
|
||||||
|
// There is an issue with how this is formatted.
|
||||||
|
// formatting should look like ./multi_line_struct_trailing_comma_never_struct_lit_width_0.rs
|
||||||
|
fn main() {
|
||||||
|
let Foo {
|
||||||
|
a, ..
|
||||||
|
} = b;
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
// rustfmt-trailing_comma: Always
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let Foo { a, .. } = b;
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
// rustfmt-trailing_comma: Never
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let Foo { a, .. } = b;
|
||||||
|
}
|
16
src/tools/rustfmt/tests/target/issue-5151/minimum_example.rs
Normal file
16
src/tools/rustfmt/tests/target/issue-5151/minimum_example.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#![feature(more_qualified_paths)]
|
||||||
|
|
||||||
|
struct Struct {}
|
||||||
|
|
||||||
|
trait Trait {
|
||||||
|
type Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trait for Struct {
|
||||||
|
type Type = Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// keep the qualified path details
|
||||||
|
let _ = <Struct as Trait>::Type {};
|
||||||
|
}
|
|
@ -608,3 +608,22 @@ fn issue_3774() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #4109
|
||||||
|
fn issue_4109() {
|
||||||
|
match () {
|
||||||
|
_ => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
{
|
||||||
|
println!("Foo");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match () {
|
||||||
|
_ => {
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
#![rustfmt::skip]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trailing Comment
|
Loading…
Add table
Add a link
Reference in a new issue