Merge pull request #2807 from topecongiro/raw-identifiers

Handle raw identifiers
This commit is contained in:
Nick Cameron 2018-06-26 08:24:34 +12:00 committed by GitHub
commit 1cca758d4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 178 additions and 67 deletions

View File

@ -21,7 +21,7 @@ use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListIte
use rewrite::{Rewrite, RewriteContext};
use shape::Shape;
use spanned::Spanned;
use utils::mk_sp;
use utils::{mk_sp, rewrite_ident};
use visitor::FmtVisitor;
use std::borrow::Cow;
@ -141,9 +141,12 @@ impl UseSegment {
}
}
fn from_path_segment(path_seg: &ast::PathSegment) -> Option<UseSegment> {
let name = path_seg.ident.name.as_str();
if name == "{{root}}" {
fn from_path_segment(
context: &RewriteContext,
path_seg: &ast::PathSegment,
) -> Option<UseSegment> {
let name = rewrite_ident(context, path_seg.ident);
if name.is_empty() || name == "{{root}}" {
return None;
}
Some(if name == "self" {
@ -231,10 +234,9 @@ impl fmt::Display for UseTree {
impl UseTree {
// Rewrite use tree with `use ` and a trailing `;`.
pub fn rewrite_top_level(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
let vis = self
.visibility
.as_ref()
.map_or(Cow::from(""), |vis| ::utils::format_visibility(&vis));
let vis = self.visibility.as_ref().map_or(Cow::from(""), |vis| {
::utils::format_visibility(context, &vis)
});
let use_str = self
.rewrite(context, shape.offset_left(vis.len())?)
.map(|s| {
@ -314,7 +316,7 @@ impl UseTree {
attrs,
};
for p in &a.prefix.segments {
if let Some(use_segment) = UseSegment::from_path_segment(p) {
if let Some(use_segment) = UseSegment::from_path_segment(context, p) {
result.path.push(use_segment);
}
}
@ -347,12 +349,12 @@ impl UseTree {
));
}
UseTreeKind::Simple(ref rename, ..) => {
let mut name = (*path_to_imported_ident(&a.prefix).name.as_str()).to_owned();
let mut name = rewrite_ident(context, path_to_imported_ident(&a.prefix)).to_owned();
let alias = rename.and_then(|ident| {
if ident == path_to_imported_ident(&a.prefix) {
None
} else {
Some(ident.to_string())
Some(rewrite_ident(context, ident).to_owned())
}
});

View File

@ -233,7 +233,7 @@ impl<'a> FnSig<'a> {
fn to_str(&self, context: &RewriteContext) -> String {
let mut result = String::with_capacity(128);
// Vis defaultness constness unsafety abi.
result.push_str(&*format_visibility(&self.visibility));
result.push_str(&*format_visibility(context, &self.visibility));
result.push_str(format_defaultness(self.defaultness));
result.push_str(format_constness(self.constness));
result.push_str(format_unsafety(self.unsafety));
@ -437,7 +437,7 @@ impl<'a> FmtVisitor<'a> {
generics: &ast::Generics,
span: Span,
) {
let enum_header = format_header("enum ", ident, vis);
let enum_header = format_header(&self.get_context(), "enum ", ident, vis);
self.push_str(&enum_header);
let enum_snippet = self.snippet(span);
@ -571,10 +571,10 @@ impl<'a> FmtVisitor<'a> {
)?,
ast::VariantData::Unit(..) => {
if let Some(ref expr) = field.node.disr_expr {
let lhs = format!("{} =", field.node.ident.name);
let lhs = format!("{} =", rewrite_ident(&context, field.node.ident));
rewrite_assign_rhs(&context, lhs, &*expr.value, shape)?
} else {
field.node.ident.name.to_string()
rewrite_ident(&context, field.node.ident).to_owned()
}
}
};
@ -797,7 +797,7 @@ fn format_impl_ref_and_type(
{
let mut result = String::with_capacity(128);
result.push_str(&format_visibility(&item.vis));
result.push_str(&format_visibility(context, &item.vis));
result.push_str(format_defaultness(defaultness));
result.push_str(format_unsafety(unsafety));
@ -916,8 +916,8 @@ pub struct StructParts<'a> {
}
impl<'a> StructParts<'a> {
fn format_header(&self) -> String {
format_header(self.prefix, self.ident, self.vis)
fn format_header(&self, context: &RewriteContext) -> String {
format_header(context, self.prefix, self.ident, self.vis)
}
fn from_variant(variant: &'a ast::Variant) -> Self {
@ -977,7 +977,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
let mut result = String::with_capacity(128);
let header = format!(
"{}{}{}trait ",
format_visibility(&item.vis),
format_visibility(context, &item.vis),
format_unsafety(unsafety),
format_auto(is_auto),
);
@ -988,7 +988,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
let shape = Shape::indented(offset, context.config).offset_left(result.len())?;
let generics_str = rewrite_generics(
context,
&item.ident.to_string(),
rewrite_ident(context, item.ident),
generics,
shape,
mk_sp(item.span.lo(), body_lo),
@ -999,7 +999,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
if !generic_bounds.is_empty() {
let ident_hi = context
.snippet_provider
.span_after(item.span, &format!("{}", item.ident));
.span_after(item.span, &item.ident.as_str());
let bound_hi = generic_bounds.last().unwrap().span().hi();
let snippet = context.snippet(mk_sp(ident_hi, bound_hi));
if contains_comment(snippet) {
@ -1135,7 +1135,7 @@ pub fn format_trait_alias(
generic_bounds: &ast::GenericBounds,
shape: Shape,
) -> Option<String> {
let alias = ident.name.as_str();
let alias = rewrite_ident(context, ident);
// 6 = "trait ", 2 = " ="
let g_shape = shape.offset_left(6)?.sub_width(2)?;
let generics_str = rewrite_generics(context, &alias, generics, g_shape, generics.span)?;
@ -1145,7 +1145,7 @@ pub fn format_trait_alias(
}
fn format_unit_struct(context: &RewriteContext, p: &StructParts, offset: Indent) -> Option<String> {
let header_str = format_header(p.prefix, p.ident, p.vis);
let header_str = format_header(context, p.prefix, p.ident, p.vis);
let generics_str = if let Some(generics) = p.generics {
let hi = if generics.where_clause.predicates.is_empty() {
generics.span.hi()
@ -1177,7 +1177,7 @@ pub fn format_struct_struct(
let mut result = String::with_capacity(1024);
let span = struct_parts.span;
let header_str = struct_parts.format_header();
let header_str = struct_parts.format_header(context);
result.push_str(&header_str);
let header_hi = span.lo() + BytePos(header_str.len() as u32);
@ -1312,7 +1312,7 @@ fn format_tuple_struct(
let mut result = String::with_capacity(1024);
let span = struct_parts.span;
let header_str = struct_parts.format_header();
let header_str = struct_parts.format_header(context);
result.push_str(&header_str);
let body_lo = if fields.is_empty() {
@ -1413,7 +1413,7 @@ pub fn rewrite_type_alias(
) -> Option<String> {
let mut result = String::with_capacity(128);
result.push_str(&format_visibility(vis));
result.push_str(&format_visibility(context, vis));
result.push_str("type ");
// 2 = `= `
@ -1424,7 +1424,13 @@ pub fn rewrite_type_alias(
context.snippet_provider.span_after(span, "type"),
ty.span.lo(),
);
let generics_str = rewrite_generics(context, &ident.to_string(), generics, g_shape, g_span)?;
let generics_str = rewrite_generics(
context,
rewrite_ident(context, ident),
generics,
g_shape,
g_span,
)?;
result.push_str(&generics_str);
let where_budget = context.budget(last_line_width(&result));
@ -1467,10 +1473,15 @@ pub fn rewrite_struct_field_prefix(
context: &RewriteContext,
field: &ast::StructField,
) -> Option<String> {
let vis = format_visibility(&field.vis);
let vis = format_visibility(context, &field.vis);
let type_annotation_spacing = type_annotation_spacing(context.config);
Some(match field.ident {
Some(name) => format!("{}{}{}:", vis, name, type_annotation_spacing.0),
Some(name) => format!(
"{}{}{}:",
vis,
rewrite_ident(context, name),
type_annotation_spacing.0
),
None => format!("{}", vis),
})
}
@ -1623,7 +1634,7 @@ fn rewrite_static(
);
let mut prefix = format!(
"{}{}{} {}{}{}",
format_visibility(static_parts.vis),
format_visibility(context, static_parts.vis),
static_parts.defaultness.map_or("", format_defaultness),
static_parts.prefix,
format_mutability(static_parts.mutability),
@ -1673,7 +1684,7 @@ pub fn rewrite_associated_type(
context: &RewriteContext,
indent: Indent,
) -> Option<String> {
let prefix = format!("type {}", ident);
let prefix = format!("type {}", rewrite_ident(context, ident));
let type_bounds_str = if let Some(bounds) = generic_bounds_opt {
if bounds.is_empty() {
@ -1881,8 +1892,13 @@ fn rewrite_fn_base(
};
let fd = fn_sig.decl;
let g_span = mk_sp(span.lo(), fd.output.span().lo());
let generics_str =
rewrite_generics(context, &ident.to_string(), fn_sig.generics, shape, g_span)?;
let generics_str = rewrite_generics(
context,
rewrite_ident(context, ident),
fn_sig.generics,
shape,
g_span,
)?;
result.push_str(&generics_str);
let snuggle_angle_bracket = generics_str
@ -2665,8 +2681,18 @@ fn rewrite_comments_before_after_where(
Some((before_comment, after_comment))
}
fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> String {
format!("{}{}{}", format_visibility(vis), item_name, ident)
fn format_header(
context: &RewriteContext,
item_name: &str,
ident: ast::Ident,
vis: &ast::Visibility,
) -> String {
format!(
"{}{}{}",
format_visibility(context, vis),
item_name,
rewrite_ident(context, ident)
)
}
#[derive(PartialEq, Eq, Clone, Copy)]
@ -2771,15 +2797,24 @@ impl Rewrite for ast::ForeignItem {
ast::ForeignItemKind::Static(ref ty, is_mutable) => {
// FIXME(#21): we're dropping potential comments in between the
// function keywords here.
let vis = format_visibility(&self.vis);
let vis = format_visibility(context, &self.vis);
let mut_str = if is_mutable { "mut " } else { "" };
let prefix = format!("{}static {}{}:", vis, mut_str, self.ident);
let prefix = format!(
"{}static {}{}:",
vis,
mut_str,
rewrite_ident(context, self.ident)
);
// 1 = ;
rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";")
}
ast::ForeignItemKind::Ty => {
let vis = format_visibility(&self.vis);
Some(format!("{}type {};", vis, self.ident))
let vis = format_visibility(context, &self.vis);
Some(format!(
"{}type {};",
vis,
rewrite_ident(context, self.ident)
))
}
ast::ForeignItemKind::Macro(ref mac) => {
rewrite_macro(mac, None, context, shape, MacroPosition::Item)
@ -2803,11 +2838,11 @@ impl Rewrite for ast::ForeignItem {
}
/// Rewrite an inline mod.
pub fn rewrite_mod(item: &ast::Item) -> String {
pub fn rewrite_mod(context: &RewriteContext, item: &ast::Item) -> String {
let mut result = String::with_capacity(32);
result.push_str(&*format_visibility(&item.vis));
result.push_str(&*format_visibility(context, &item.vis));
result.push_str("mod ");
result.push_str(&item.ident.to_string());
result.push_str(rewrite_ident(context, item.ident));
result.push(';');
result
}

View File

@ -43,7 +43,7 @@ use overflow;
use rewrite::{Rewrite, RewriteContext};
use shape::{Indent, Shape};
use spanned::Spanned;
use utils::{format_visibility, mk_sp, wrap_str};
use utils::{format_visibility, mk_sp, rewrite_ident, wrap_str};
const FORCED_BRACKET_MACROS: &[&str] = &["vec!"];
@ -116,10 +116,14 @@ fn parse_macro_arg(parser: &mut Parser) -> Option<MacroArg> {
}
/// Rewrite macro name without using pretty-printer if possible.
fn rewrite_macro_name(path: &ast::Path, extra_ident: Option<ast::Ident>) -> String {
fn rewrite_macro_name(
context: &RewriteContext,
path: &ast::Path,
extra_ident: Option<ast::Ident>,
) -> String {
let name = if path.segments.len() == 1 {
// Avoid using pretty-printer in the common case.
format!("{}!", path.segments[0].ident)
format!("{}!", rewrite_ident(context, path.segments[0].ident))
} else {
format!("{}!", path)
};
@ -170,7 +174,7 @@ pub fn rewrite_macro_inner(
let original_style = macro_style(mac, context);
let macro_name = rewrite_macro_name(&mac.node.path, extra_ident);
let macro_name = rewrite_macro_name(context, &mac.node.path, extra_ident);
let style = if FORCED_BRACKET_MACROS.contains(&&macro_name[..]) {
DelimToken::Bracket
@ -361,11 +365,11 @@ pub fn rewrite_macro_def(
let mut result = if def.legacy {
String::from("macro_rules!")
} else {
format!("{}macro", format_visibility(vis))
format!("{}macro", format_visibility(context, vis))
};
result += " ";
result += &ident.name.as_str();
result += rewrite_ident(context, ident);
let multi_branch_style = def.legacy || parsed_def.branches.len() != 1;
@ -1339,7 +1343,7 @@ fn format_lazy_static(context: &RewriteContext, shape: Shape, ts: &TokenStream)
while parser.token != Token::Eof {
// Parse a `lazy_static!` item.
let vis = ::utils::format_visibility(&parse_or!(parse_visibility, false));
let vis = ::utils::format_visibility(context, &parse_or!(parse_visibility, false));
parser.eat_keyword(symbol::keywords::Static);
parser.eat_keyword(symbol::keywords::Ref);
let id = parse_or!(parse_ident);

View File

@ -28,7 +28,7 @@ use rewrite::{Rewrite, RewriteContext};
use shape::Shape;
use spanned::Spanned;
use types::{rewrite_path, PathContext};
use utils::{format_mutability, mk_sp};
use utils::{format_mutability, mk_sp, rewrite_ident};
/// Returns true if the given pattern is short. A short pattern is defined by the following grammer:
///
@ -74,7 +74,7 @@ impl Rewrite for Pat {
BindingMode::ByValue(mutability) => ("", mutability),
};
let mut_infix = format_mutability(mutability);
let id_str = ident.name.to_string();
let id_str = rewrite_ident(context, ident);
let sub_pat = match *sub_pat {
Some(ref p) => {
// 3 - ` @ `.
@ -246,7 +246,7 @@ impl Rewrite for FieldPat {
pat
} else {
let pat_str = pat?;
let id_str = self.ident.to_string();
let id_str = rewrite_ident(context, self.ident);
let one_line_width = id_str.len() + 2 + pat_str.len();
if one_line_width <= shape.width {
Some(format!("{}: {}", id_str, pat_str))

View File

@ -100,7 +100,7 @@ fn rewrite_reorderable_item(
let item_str = match item.node {
ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item)?,
ast::ItemKind::Mod(..) => rewrite_mod(item),
ast::ItemKind::Mod(..) => rewrite_mod(context, item),
_ => return None,
};

View File

@ -29,7 +29,7 @@ use shape::Shape;
use spanned::Spanned;
use utils::{
colon_spaces, extra_offset, first_line_width, format_abi, format_mutability, last_line_width,
mk_sp,
mk_sp, rewrite_ident,
};
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
@ -187,8 +187,10 @@ impl<'a> Rewrite for SegmentParam<'a> {
SegmentParam::Type(ty) => ty.rewrite(context, shape),
SegmentParam::Binding(binding) => {
let mut result = match context.config.type_punctuation_density() {
TypeDensity::Wide => format!("{} = ", binding.ident),
TypeDensity::Compressed => format!("{}=", binding.ident),
TypeDensity::Wide => format!("{} = ", rewrite_ident(context, binding.ident)),
TypeDensity::Compressed => {
format!("{}=", rewrite_ident(context, binding.ident))
}
};
let budget = shape.width.checked_sub(result.len())?;
let rewrite = binding
@ -220,7 +222,7 @@ fn rewrite_segment(
shape: Shape,
) -> Option<String> {
let mut result = String::with_capacity(128);
result.push_str(&segment.ident.name.as_str());
result.push_str(rewrite_ident(context, segment.ident));
let ident_len = result.len();
let shape = if context.use_block_indent() {
@ -496,8 +498,8 @@ fn rewrite_bounded_lifetime(
}
impl Rewrite for ast::Lifetime {
fn rewrite(&self, _: &RewriteContext, _: Shape) -> Option<String> {
Some(self.ident.to_string())
fn rewrite(&self, context: &RewriteContext, _: Shape) -> Option<String> {
Some(rewrite_ident(context, self.ident).to_owned())
}
}
@ -532,7 +534,7 @@ impl Rewrite for ast::GenericParam {
Some(ref rw) if !rw.is_empty() => result.push_str(&format!("{} ", rw)),
_ => (),
}
result.push_str(&self.ident.to_string());
result.push_str(rewrite_ident(context, self.ident));
if !self.bounds.is_empty() {
result.push_str(type_bound_colon(context));
result.push_str(&self.bounds.rewrite(context, shape)?)

View File

@ -24,6 +24,10 @@ use shape::Shape;
pub const DEPR_SKIP_ANNOTATION: &str = "rustfmt_skip";
pub const SKIP_ANNOTATION: &str = "rustfmt::skip";
pub fn rewrite_ident<'a>(context: &'a RewriteContext, ident: ast::Ident) -> &'a str {
context.snippet(ident.span)
}
// Computes the length of a string's last line, minus offset.
pub fn extra_offset(text: &str, shape: Shape) -> usize {
match text.rfind('\n') {
@ -34,7 +38,7 @@ pub fn extra_offset(text: &str, shape: Shape) -> usize {
}
// Uses Cow to avoid allocating in the common cases.
pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> {
pub fn format_visibility(context: &RewriteContext, vis: &Visibility) -> Cow<'static, str> {
match vis.node {
VisibilityKind::Public => Cow::from("pub "),
VisibilityKind::Inherited => Cow::from(""),
@ -42,7 +46,7 @@ pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> {
VisibilityKind::Crate(CrateSugar::JustCrate) => Cow::from("crate "),
VisibilityKind::Restricted { ref path, .. } => {
let Path { ref segments, .. } = **path;
let mut segments_iter = segments.iter().map(|seg| seg.ident.name.to_string());
let mut segments_iter = segments.iter().map(|seg| rewrite_ident(context, seg.ident));
if path.is_global() {
segments_iter
.next()

View File

@ -24,7 +24,7 @@ use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separat
use rewrite::{Rewrite, RewriteContext};
use shape::{Indent, Shape};
use spanned::Spanned;
use utils::{contains_skip, is_attributes_extendable, mk_sp};
use utils::{contains_skip, is_attributes_extendable, mk_sp, rewrite_ident};
pub trait AlignedItem {
fn skip(&self) -> bool;
@ -88,7 +88,7 @@ impl AlignedItem for ast::Field {
fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
let attrs_str = self.attrs.rewrite(context, shape)?;
let name = &self.ident.name.to_string();
let name = rewrite_ident(context, self.ident);
let missing_span = if self.attrs.is_empty() {
mk_sp(self.span.lo(), self.span.lo())
} else {

View File

@ -28,7 +28,7 @@ use shape::{Indent, Shape};
use spanned::Spanned;
use utils::{
self, contains_skip, count_newlines, inner_attributes, mk_sp, ptr_vec_to_ref_vec,
DEPR_SKIP_ANNOTATION,
rewrite_ident, DEPR_SKIP_ANNOTATION,
};
use {ErrorKind, FormatReport, FormattingError};
@ -682,9 +682,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
attrs: &[ast::Attribute],
is_internal: bool,
) {
self.push_str(&*utils::format_visibility(vis));
let vis_str = utils::format_visibility(&self.get_context(), vis);
self.push_str(&*vis_str);
self.push_str("mod ");
self.push_str(&ident.to_string());
// Calling `to_owned()` to work around borrow checker.
let ident_str = rewrite_ident(&self.get_context(), ident).to_owned();
self.push_str(&ident_str);
if is_internal {
match self.config.brace_style() {

View File

@ -0,0 +1,61 @@
#![feature(custom_attribute)]
#![feature(raw_identifiers)]
#![feature(extern_types)]
#![allow(invalid_type_param_default)]
#![allow(unused_attributes)]
use r#foo as r#alias_foo;
fn main() {
#[r#attr]
r#foo::r#bar();
let r#local = 3;
let r#async = r#foo(r#local);
r#macro!();
if let r#sub_pat @ r#Foo(_) = r#Foo(3) {}
match r#async {
r#Foo | r#Bar => r#foo(),
}
}
fn r#bar<'a, r#T>(r#x: &'a r#T) {}
mod r#foo {
pub fn r#bar() {}
}
enum r#Foo {
r#Bar {},
}
struct r#Struct {
r#field: r#FieldType,
}
trait r#Trait {
type r#Type;
}
impl r#Trait for r#Impl {
type r#Type = r#u32;
fn r#xxx(r#fjio: r#u32) {}
}
extern "C" {
type r#ccc;
static r#static_val: u32;
}
macro_rules! r#macro {
() => {};
}
macro_rules! foo {
($x:expr) => {
let r#catch = $x + 1;
println!("{}", r#catch);
};
}