Add Version information to UseSegment
There are some proposed import sorting changes for raw identifier `r#`. These changes constitute a breaking change, and need to be version gagted. Before version gating those changes we add the version information to the `UseSegment`.
This commit is contained in:
parent
5ae94cc6b8
commit
795efb2068
2 changed files with 206 additions and 115 deletions
311
src/imports.rs
311
src/imports.rs
|
|
@ -15,7 +15,7 @@ use rustc_span::{
|
|||
use crate::comment::combine_strs_with_missing_comments;
|
||||
use crate::config::lists::*;
|
||||
use crate::config::ImportGranularity;
|
||||
use crate::config::{Edition, IndentStyle};
|
||||
use crate::config::{Edition, IndentStyle, Version};
|
||||
use crate::lists::{
|
||||
definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator,
|
||||
};
|
||||
|
|
@ -92,7 +92,7 @@ impl<'a> FmtVisitor<'a> {
|
|||
|
||||
// FIXME we do a lot of allocation to make our own representation.
|
||||
#[derive(Clone, Eq, Hash, PartialEq)]
|
||||
pub(crate) enum UseSegment {
|
||||
pub(crate) enum UseSegmentKind {
|
||||
Ident(String, Option<String>),
|
||||
Slf(Option<String>),
|
||||
Super(Option<String>),
|
||||
|
|
@ -101,6 +101,12 @@ pub(crate) enum UseSegment {
|
|||
List(Vec<UseTree>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub(crate) struct UseSegment {
|
||||
pub(crate) kind: UseSegmentKind,
|
||||
pub(crate) version: Version,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct UseTree {
|
||||
pub(crate) path: Vec<UseSegment>,
|
||||
|
|
@ -134,34 +140,38 @@ impl Spanned for UseTree {
|
|||
impl UseSegment {
|
||||
// Clone a version of self with any top-level alias removed.
|
||||
fn remove_alias(&self) -> UseSegment {
|
||||
match *self {
|
||||
UseSegment::Ident(ref s, _) => UseSegment::Ident(s.clone(), None),
|
||||
UseSegment::Slf(_) => UseSegment::Slf(None),
|
||||
UseSegment::Super(_) => UseSegment::Super(None),
|
||||
UseSegment::Crate(_) => UseSegment::Crate(None),
|
||||
_ => self.clone(),
|
||||
let kind = match self.kind {
|
||||
UseSegmentKind::Ident(ref s, _) => UseSegmentKind::Ident(s.clone(), None),
|
||||
UseSegmentKind::Slf(_) => UseSegmentKind::Slf(None),
|
||||
UseSegmentKind::Super(_) => UseSegmentKind::Super(None),
|
||||
UseSegmentKind::Crate(_) => UseSegmentKind::Crate(None),
|
||||
_ => return self.clone(),
|
||||
};
|
||||
UseSegment {
|
||||
kind,
|
||||
version: self.version,
|
||||
}
|
||||
}
|
||||
|
||||
// Check if self == other with their aliases removed.
|
||||
fn equal_except_alias(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(UseSegment::Ident(ref s1, _), UseSegment::Ident(ref s2, _)) => s1 == s2,
|
||||
(UseSegment::Slf(_), UseSegment::Slf(_))
|
||||
| (UseSegment::Super(_), UseSegment::Super(_))
|
||||
| (UseSegment::Crate(_), UseSegment::Crate(_))
|
||||
| (UseSegment::Glob, UseSegment::Glob) => true,
|
||||
(UseSegment::List(ref list1), UseSegment::List(ref list2)) => list1 == list2,
|
||||
match (&self.kind, &other.kind) {
|
||||
(UseSegmentKind::Ident(ref s1, _), UseSegmentKind::Ident(ref s2, _)) => s1 == s2,
|
||||
(UseSegmentKind::Slf(_), UseSegmentKind::Slf(_))
|
||||
| (UseSegmentKind::Super(_), UseSegmentKind::Super(_))
|
||||
| (UseSegmentKind::Crate(_), UseSegmentKind::Crate(_))
|
||||
| (UseSegmentKind::Glob, UseSegmentKind::Glob) => true,
|
||||
(UseSegmentKind::List(ref list1), UseSegmentKind::List(ref list2)) => list1 == list2,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_alias(&self) -> Option<&str> {
|
||||
match self {
|
||||
UseSegment::Ident(_, a)
|
||||
| UseSegment::Slf(a)
|
||||
| UseSegment::Super(a)
|
||||
| UseSegment::Crate(a) => a.as_deref(),
|
||||
match &self.kind {
|
||||
UseSegmentKind::Ident(_, a)
|
||||
| UseSegmentKind::Slf(a)
|
||||
| UseSegmentKind::Super(a)
|
||||
| UseSegmentKind::Crate(a) => a.as_deref(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -175,19 +185,24 @@ impl UseSegment {
|
|||
if name.is_empty() || name == "{{root}}" {
|
||||
return None;
|
||||
}
|
||||
Some(match name {
|
||||
"self" => UseSegment::Slf(None),
|
||||
"super" => UseSegment::Super(None),
|
||||
"crate" => UseSegment::Crate(None),
|
||||
let kind = match name {
|
||||
"self" => UseSegmentKind::Slf(None),
|
||||
"super" => UseSegmentKind::Super(None),
|
||||
"crate" => UseSegmentKind::Crate(None),
|
||||
_ => {
|
||||
let mod_sep = if modsep { "::" } else { "" };
|
||||
UseSegment::Ident(format!("{}{}", mod_sep, name), None)
|
||||
UseSegmentKind::Ident(format!("{}{}", mod_sep, name), None)
|
||||
}
|
||||
};
|
||||
|
||||
Some(UseSegment {
|
||||
kind,
|
||||
version: context.config.version(),
|
||||
})
|
||||
}
|
||||
|
||||
fn contains_comment(&self) -> bool {
|
||||
if let UseSegment::List(list) = self {
|
||||
if let UseSegmentKind::List(list) = &self.kind {
|
||||
list.iter().any(|subtree| subtree.contains_comment())
|
||||
} else {
|
||||
false
|
||||
|
|
@ -254,20 +269,38 @@ impl fmt::Debug for UseTree {
|
|||
|
||||
impl fmt::Debug for UseSegment {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self, f)
|
||||
fmt::Display::fmt(&self.kind, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for UseSegment {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.kind, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for UseSegment {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.kind.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for UseSegmentKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for UseSegmentKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
UseSegment::Glob => write!(f, "*"),
|
||||
UseSegment::Ident(ref s, Some(ref alias)) => write!(f, "{} as {}", s, alias),
|
||||
UseSegment::Ident(ref s, None) => write!(f, "{}", s),
|
||||
UseSegment::Slf(..) => write!(f, "self"),
|
||||
UseSegment::Super(..) => write!(f, "super"),
|
||||
UseSegment::Crate(..) => write!(f, "crate"),
|
||||
UseSegment::List(ref list) => {
|
||||
UseSegmentKind::Glob => write!(f, "*"),
|
||||
UseSegmentKind::Ident(ref s, Some(ref alias)) => write!(f, "{} as {}", s, alias),
|
||||
UseSegmentKind::Ident(ref s, None) => write!(f, "{}", s),
|
||||
UseSegmentKind::Slf(..) => write!(f, "self"),
|
||||
UseSegmentKind::Super(..) => write!(f, "super"),
|
||||
UseSegmentKind::Crate(..) => write!(f, "crate"),
|
||||
UseSegmentKind::List(ref list) => {
|
||||
write!(f, "{{")?;
|
||||
for (i, item) in list.iter().enumerate() {
|
||||
if i != 0 {
|
||||
|
|
@ -411,13 +444,19 @@ impl UseTree {
|
|||
}
|
||||
}
|
||||
|
||||
let version = context.config.version();
|
||||
|
||||
match a.kind {
|
||||
UseTreeKind::Glob => {
|
||||
// in case of a global path and the glob starts at the root, e.g., "::*"
|
||||
if a.prefix.segments.len() == 1 && leading_modsep {
|
||||
result.path.push(UseSegment::Ident("".to_owned(), None));
|
||||
let kind = UseSegmentKind::Ident("".to_owned(), None);
|
||||
result.path.push(UseSegment { kind, version });
|
||||
}
|
||||
result.path.push(UseSegment::Glob);
|
||||
result.path.push(UseSegment {
|
||||
kind: UseSegmentKind::Glob,
|
||||
version,
|
||||
});
|
||||
}
|
||||
UseTreeKind::Nested(ref list) => {
|
||||
// Extract comments between nested use items.
|
||||
|
|
@ -438,16 +477,18 @@ impl UseTree {
|
|||
// in case of a global path and the nested list starts at the root,
|
||||
// e.g., "::{foo, bar}"
|
||||
if a.prefix.segments.len() == 1 && leading_modsep {
|
||||
result.path.push(UseSegment::Ident("".to_owned(), None));
|
||||
let kind = UseSegmentKind::Ident("".to_owned(), None);
|
||||
result.path.push(UseSegment { kind, version });
|
||||
}
|
||||
result.path.push(UseSegment::List(
|
||||
let kind = UseSegmentKind::List(
|
||||
list.iter()
|
||||
.zip(items)
|
||||
.map(|(t, list_item)| {
|
||||
Self::from_ast(context, &t.0, Some(list_item), None, None, None)
|
||||
})
|
||||
.collect(),
|
||||
));
|
||||
);
|
||||
result.path.push(UseSegment { kind, version });
|
||||
}
|
||||
UseTreeKind::Simple(ref rename, ..) => {
|
||||
// If the path has leading double colons and is composed of only 2 segments, then we
|
||||
|
|
@ -469,13 +510,15 @@ impl UseTree {
|
|||
Some(rewrite_ident(context, ident).to_owned())
|
||||
}
|
||||
});
|
||||
let segment = match name.as_ref() {
|
||||
"self" => UseSegment::Slf(alias),
|
||||
"super" => UseSegment::Super(alias),
|
||||
"crate" => UseSegment::Crate(alias),
|
||||
_ => UseSegment::Ident(name, alias),
|
||||
let kind = match name.as_ref() {
|
||||
"self" => UseSegmentKind::Slf(alias),
|
||||
"super" => UseSegmentKind::Super(alias),
|
||||
"crate" => UseSegmentKind::Crate(alias),
|
||||
_ => UseSegmentKind::Ident(name, alias),
|
||||
};
|
||||
|
||||
let segment = UseSegment { kind, version };
|
||||
|
||||
// `name` is already in result.
|
||||
result.path.pop();
|
||||
result.path.push(segment);
|
||||
|
|
@ -492,13 +535,13 @@ impl UseTree {
|
|||
let mut aliased_self = false;
|
||||
|
||||
// Remove foo::{} or self without attributes.
|
||||
match last {
|
||||
match last.kind {
|
||||
_ if self.attrs.is_some() => (),
|
||||
UseSegment::List(ref list) if list.is_empty() => {
|
||||
UseSegmentKind::List(ref list) if list.is_empty() => {
|
||||
self.path = vec![];
|
||||
return self;
|
||||
}
|
||||
UseSegment::Slf(None) if self.path.is_empty() && self.visibility.is_some() => {
|
||||
UseSegmentKind::Slf(None) if self.path.is_empty() && self.visibility.is_some() => {
|
||||
self.path = vec![];
|
||||
return self;
|
||||
}
|
||||
|
|
@ -506,15 +549,19 @@ impl UseTree {
|
|||
}
|
||||
|
||||
// Normalise foo::self -> foo.
|
||||
if let UseSegment::Slf(None) = last {
|
||||
if let UseSegmentKind::Slf(None) = last.kind {
|
||||
if !self.path.is_empty() {
|
||||
return self;
|
||||
}
|
||||
}
|
||||
|
||||
// Normalise foo::self as bar -> foo as bar.
|
||||
if let UseSegment::Slf(_) = last {
|
||||
if let Some(UseSegment::Ident(_, None)) = self.path.last() {
|
||||
if let UseSegmentKind::Slf(_) = last.kind {
|
||||
if let Some(UseSegment {
|
||||
kind: UseSegmentKind::Ident(_, None),
|
||||
..
|
||||
}) = self.path.last()
|
||||
{
|
||||
aliased_self = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -522,9 +569,12 @@ impl UseTree {
|
|||
let mut done = false;
|
||||
if aliased_self {
|
||||
match self.path.last_mut() {
|
||||
Some(UseSegment::Ident(_, ref mut old_rename)) => {
|
||||
Some(UseSegment {
|
||||
kind: UseSegmentKind::Ident(_, ref mut old_rename),
|
||||
..
|
||||
}) => {
|
||||
assert!(old_rename.is_none());
|
||||
if let UseSegment::Slf(Some(rename)) = last.clone() {
|
||||
if let UseSegmentKind::Slf(Some(rename)) = last.clone().kind {
|
||||
*old_rename = Some(rename);
|
||||
done = true;
|
||||
}
|
||||
|
|
@ -538,15 +588,15 @@ impl UseTree {
|
|||
}
|
||||
|
||||
// Normalise foo::{bar} -> foo::bar
|
||||
if let UseSegment::List(ref list) = last {
|
||||
if let UseSegmentKind::List(ref list) = last.kind {
|
||||
if list.len() == 1 && list[0].to_string() != "self" {
|
||||
normalize_sole_list = true;
|
||||
}
|
||||
}
|
||||
|
||||
if normalize_sole_list {
|
||||
match last {
|
||||
UseSegment::List(list) => {
|
||||
match last.kind {
|
||||
UseSegmentKind::List(list) => {
|
||||
for seg in &list[0].path {
|
||||
self.path.push(seg.clone());
|
||||
}
|
||||
|
|
@ -557,10 +607,13 @@ impl UseTree {
|
|||
}
|
||||
|
||||
// Recursively normalize elements of a list use (including sorting the list).
|
||||
if let UseSegment::List(list) = last {
|
||||
if let UseSegmentKind::List(list) = last.kind {
|
||||
let mut list = list.into_iter().map(UseTree::normalize).collect::<Vec<_>>();
|
||||
list.sort();
|
||||
last = UseSegment::List(list);
|
||||
last = UseSegment {
|
||||
kind: UseSegmentKind::List(list),
|
||||
version: last.version,
|
||||
};
|
||||
}
|
||||
|
||||
self.path.push(last);
|
||||
|
|
@ -620,10 +673,10 @@ impl UseTree {
|
|||
if self.path.is_empty() || self.contains_comment() {
|
||||
return vec![self];
|
||||
}
|
||||
match self.path.clone().last().unwrap() {
|
||||
UseSegment::List(list) => {
|
||||
match &self.path.clone().last().unwrap().kind {
|
||||
UseSegmentKind::List(list) => {
|
||||
if list.len() == 1 && list[0].path.len() == 1 {
|
||||
if let UseSegment::Slf(..) = list[0].path[0] {
|
||||
if let UseSegmentKind::Slf(..) = list[0].path[0].kind {
|
||||
return vec![self];
|
||||
};
|
||||
}
|
||||
|
|
@ -671,12 +724,15 @@ impl UseTree {
|
|||
|
||||
/// If this tree ends in `::self`, rewrite it to `::{self}`.
|
||||
fn nest_trailing_self(mut self) -> UseTree {
|
||||
if let Some(UseSegment::Slf(..)) = self.path.last() {
|
||||
if let Some(UseSegment {
|
||||
kind: UseSegmentKind::Slf(..),
|
||||
..
|
||||
}) = self.path.last()
|
||||
{
|
||||
let self_segment = self.path.pop().unwrap();
|
||||
self.path.push(UseSegment::List(vec![UseTree::from_path(
|
||||
vec![self_segment],
|
||||
DUMMY_SP,
|
||||
)]));
|
||||
let version = self_segment.version;
|
||||
let kind = UseSegmentKind::List(vec![UseTree::from_path(vec![self_segment], DUMMY_SP)]);
|
||||
self.path.push(UseSegment { kind, version });
|
||||
}
|
||||
self
|
||||
}
|
||||
|
|
@ -692,7 +748,8 @@ fn merge_rest(
|
|||
return None;
|
||||
}
|
||||
if a.len() != len && b.len() != len {
|
||||
if let UseSegment::List(ref list) = a[len] {
|
||||
let version = a[len].version;
|
||||
if let UseSegmentKind::List(ref list) = a[len].kind {
|
||||
let mut list = list.clone();
|
||||
merge_use_trees_inner(
|
||||
&mut list,
|
||||
|
|
@ -700,7 +757,8 @@ fn merge_rest(
|
|||
merge_by,
|
||||
);
|
||||
let mut new_path = b[..len].to_vec();
|
||||
new_path.push(UseSegment::List(list));
|
||||
let kind = UseSegmentKind::List(list);
|
||||
new_path.push(UseSegment { kind, version });
|
||||
return Some(new_path);
|
||||
}
|
||||
} else if len == 1 {
|
||||
|
|
@ -709,15 +767,28 @@ fn merge_rest(
|
|||
} else {
|
||||
(&b[0], &a[1..])
|
||||
};
|
||||
let kind = UseSegmentKind::Slf(common.get_alias().map(ToString::to_string));
|
||||
let version = a[0].version;
|
||||
let mut list = vec![UseTree::from_path(
|
||||
vec![UseSegment::Slf(common.get_alias().map(ToString::to_string))],
|
||||
vec![UseSegment { kind, version }],
|
||||
DUMMY_SP,
|
||||
)];
|
||||
match rest {
|
||||
[UseSegment::List(rest_list)] => list.extend(rest_list.clone()),
|
||||
[
|
||||
UseSegment {
|
||||
kind: UseSegmentKind::List(rest_list),
|
||||
..
|
||||
},
|
||||
] => list.extend(rest_list.clone()),
|
||||
_ => list.push(UseTree::from_path(rest.to_vec(), DUMMY_SP)),
|
||||
}
|
||||
return Some(vec![b[0].clone(), UseSegment::List(list)]);
|
||||
return Some(vec![
|
||||
b[0].clone(),
|
||||
UseSegment {
|
||||
kind: UseSegmentKind::List(list),
|
||||
version,
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
len -= 1;
|
||||
}
|
||||
|
|
@ -727,7 +798,9 @@ fn merge_rest(
|
|||
];
|
||||
list.sort();
|
||||
let mut new_path = b[..len].to_vec();
|
||||
new_path.push(UseSegment::List(list));
|
||||
let kind = UseSegmentKind::List(list);
|
||||
let version = a[0].version;
|
||||
new_path.push(UseSegment { kind, version });
|
||||
Some(new_path)
|
||||
}
|
||||
|
||||
|
|
@ -805,24 +878,24 @@ impl PartialOrd for UseTree {
|
|||
}
|
||||
impl Ord for UseSegment {
|
||||
fn cmp(&self, other: &UseSegment) -> Ordering {
|
||||
use self::UseSegment::*;
|
||||
use self::UseSegmentKind::*;
|
||||
|
||||
fn is_upper_snake_case(s: &str) -> bool {
|
||||
s.chars()
|
||||
.all(|c| c.is_uppercase() || c == '_' || c.is_numeric())
|
||||
}
|
||||
|
||||
match (self, other) {
|
||||
(&Slf(ref a), &Slf(ref b))
|
||||
| (&Super(ref a), &Super(ref b))
|
||||
| (&Crate(ref a), &Crate(ref b)) => match (a, b) {
|
||||
match (&self.kind, &other.kind) {
|
||||
(Slf(ref a), Slf(ref b))
|
||||
| (Super(ref a), Super(ref b))
|
||||
| (Crate(ref a), Crate(ref b)) => match (a, b) {
|
||||
(Some(sa), Some(sb)) => {
|
||||
sa.trim_start_matches("r#").cmp(sb.trim_start_matches("r#"))
|
||||
}
|
||||
(_, _) => a.cmp(b),
|
||||
},
|
||||
(&Glob, &Glob) => Ordering::Equal,
|
||||
(&Ident(ref pia, ref aa), &Ident(ref pib, ref ab)) => {
|
||||
(Glob, Glob) => Ordering::Equal,
|
||||
(Ident(ref pia, ref aa), Ident(ref pib, ref ab)) => {
|
||||
let ia = pia.trim_start_matches("r#");
|
||||
let ib = pib.trim_start_matches("r#");
|
||||
// snake_case < CamelCase < UPPER_SNAKE_CASE
|
||||
|
|
@ -851,7 +924,7 @@ impl Ord for UseSegment {
|
|||
(None, None) => Ordering::Equal,
|
||||
}
|
||||
}
|
||||
(&List(ref a), &List(ref b)) => {
|
||||
(List(ref a), List(ref b)) => {
|
||||
for (a, b) in a.iter().zip(b.iter()) {
|
||||
let ord = a.cmp(b);
|
||||
if ord != Ordering::Equal {
|
||||
|
|
@ -861,16 +934,16 @@ impl Ord for UseSegment {
|
|||
|
||||
a.len().cmp(&b.len())
|
||||
}
|
||||
(&Slf(_), _) => Ordering::Less,
|
||||
(_, &Slf(_)) => Ordering::Greater,
|
||||
(&Super(_), _) => Ordering::Less,
|
||||
(_, &Super(_)) => Ordering::Greater,
|
||||
(&Crate(_), _) => Ordering::Less,
|
||||
(_, &Crate(_)) => Ordering::Greater,
|
||||
(&Ident(..), _) => Ordering::Less,
|
||||
(_, &Ident(..)) => Ordering::Greater,
|
||||
(&Glob, _) => Ordering::Less,
|
||||
(_, &Glob) => Ordering::Greater,
|
||||
(Slf(_), _) => Ordering::Less,
|
||||
(_, Slf(_)) => Ordering::Greater,
|
||||
(Super(_), _) => Ordering::Less,
|
||||
(_, Super(_)) => Ordering::Greater,
|
||||
(Crate(_), _) => Ordering::Less,
|
||||
(_, Crate(_)) => Ordering::Greater,
|
||||
(Ident(..), _) => Ordering::Less,
|
||||
(_, Ident(..)) => Ordering::Greater,
|
||||
(Glob, _) => Ordering::Less,
|
||||
(_, Glob) => Ordering::Greater,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -914,7 +987,7 @@ fn rewrite_nested_use_tree(
|
|||
}
|
||||
let has_nested_list = use_tree_list.iter().any(|use_segment| {
|
||||
use_segment.path.last().map_or(false, |last_segment| {
|
||||
matches!(last_segment, UseSegment::List(..))
|
||||
matches!(last_segment.kind, UseSegmentKind::List(..))
|
||||
})
|
||||
});
|
||||
|
||||
|
|
@ -965,17 +1038,19 @@ fn rewrite_nested_use_tree(
|
|||
|
||||
impl Rewrite for UseSegment {
|
||||
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
|
||||
Some(match self {
|
||||
UseSegment::Ident(ref ident, Some(ref rename)) => format!("{} as {}", ident, rename),
|
||||
UseSegment::Ident(ref ident, None) => ident.clone(),
|
||||
UseSegment::Slf(Some(ref rename)) => format!("self as {}", rename),
|
||||
UseSegment::Slf(None) => "self".to_owned(),
|
||||
UseSegment::Super(Some(ref rename)) => format!("super as {}", rename),
|
||||
UseSegment::Super(None) => "super".to_owned(),
|
||||
UseSegment::Crate(Some(ref rename)) => format!("crate as {}", rename),
|
||||
UseSegment::Crate(None) => "crate".to_owned(),
|
||||
UseSegment::Glob => "*".to_owned(),
|
||||
UseSegment::List(ref use_tree_list) => rewrite_nested_use_tree(
|
||||
Some(match self.kind {
|
||||
UseSegmentKind::Ident(ref ident, Some(ref rename)) => {
|
||||
format!("{} as {}", ident, rename)
|
||||
}
|
||||
UseSegmentKind::Ident(ref ident, None) => ident.clone(),
|
||||
UseSegmentKind::Slf(Some(ref rename)) => format!("self as {}", rename),
|
||||
UseSegmentKind::Slf(None) => "self".to_owned(),
|
||||
UseSegmentKind::Super(Some(ref rename)) => format!("super as {}", rename),
|
||||
UseSegmentKind::Super(None) => "super".to_owned(),
|
||||
UseSegmentKind::Crate(Some(ref rename)) => format!("crate as {}", rename),
|
||||
UseSegmentKind::Crate(None) => "crate".to_owned(),
|
||||
UseSegmentKind::Glob => "*".to_owned(),
|
||||
UseSegmentKind::List(ref use_tree_list) => rewrite_nested_use_tree(
|
||||
context,
|
||||
use_tree_list,
|
||||
// 1 = "{" and "}"
|
||||
|
|
@ -1024,6 +1099,7 @@ mod test {
|
|||
|
||||
struct Parser<'a> {
|
||||
input: Peekable<Chars<'a>>,
|
||||
version: Version,
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
|
|
@ -1036,34 +1112,40 @@ mod test {
|
|||
}
|
||||
|
||||
fn push_segment(
|
||||
&self,
|
||||
result: &mut Vec<UseSegment>,
|
||||
buf: &mut String,
|
||||
alias_buf: &mut Option<String>,
|
||||
) {
|
||||
let version = self.version;
|
||||
if !buf.is_empty() {
|
||||
let mut alias = None;
|
||||
swap(alias_buf, &mut alias);
|
||||
|
||||
match buf.as_ref() {
|
||||
"self" => {
|
||||
result.push(UseSegment::Slf(alias));
|
||||
let kind = UseSegmentKind::Slf(alias);
|
||||
result.push(UseSegment { kind, version });
|
||||
*buf = String::new();
|
||||
*alias_buf = None;
|
||||
}
|
||||
"super" => {
|
||||
result.push(UseSegment::Super(alias));
|
||||
let kind = UseSegmentKind::Super(alias);
|
||||
result.push(UseSegment { kind, version });
|
||||
*buf = String::new();
|
||||
*alias_buf = None;
|
||||
}
|
||||
"crate" => {
|
||||
result.push(UseSegment::Crate(alias));
|
||||
let kind = UseSegmentKind::Crate(alias);
|
||||
result.push(UseSegment { kind, version });
|
||||
*buf = String::new();
|
||||
*alias_buf = None;
|
||||
}
|
||||
_ => {
|
||||
let mut name = String::new();
|
||||
swap(buf, &mut name);
|
||||
result.push(UseSegment::Ident(name, alias));
|
||||
let kind = UseSegmentKind::Ident(name, alias);
|
||||
result.push(UseSegment { kind, version });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1078,21 +1160,29 @@ mod test {
|
|||
'{' => {
|
||||
assert!(buf.is_empty());
|
||||
self.bump();
|
||||
result.push(UseSegment::List(self.parse_list()));
|
||||
let kind = UseSegmentKind::List(self.parse_list());
|
||||
result.push(UseSegment {
|
||||
kind,
|
||||
version: self.version,
|
||||
});
|
||||
self.eat('}');
|
||||
}
|
||||
'*' => {
|
||||
assert!(buf.is_empty());
|
||||
self.bump();
|
||||
result.push(UseSegment::Glob);
|
||||
let kind = UseSegmentKind::Glob;
|
||||
result.push(UseSegment {
|
||||
kind,
|
||||
version: self.version,
|
||||
});
|
||||
}
|
||||
':' => {
|
||||
self.bump();
|
||||
self.eat(':');
|
||||
Self::push_segment(&mut result, &mut buf, &mut alias_buf);
|
||||
self.push_segment(&mut result, &mut buf, &mut alias_buf);
|
||||
}
|
||||
'}' | ',' => {
|
||||
Self::push_segment(&mut result, &mut buf, &mut alias_buf);
|
||||
self.push_segment(&mut result, &mut buf, &mut alias_buf);
|
||||
return UseTree {
|
||||
path: result,
|
||||
span: DUMMY_SP,
|
||||
|
|
@ -1118,7 +1208,7 @@ mod test {
|
|||
}
|
||||
}
|
||||
}
|
||||
Self::push_segment(&mut result, &mut buf, &mut alias_buf);
|
||||
self.push_segment(&mut result, &mut buf, &mut alias_buf);
|
||||
UseTree {
|
||||
path: result,
|
||||
span: DUMMY_SP,
|
||||
|
|
@ -1144,6 +1234,7 @@ mod test {
|
|||
|
||||
let mut parser = Parser {
|
||||
input: s.chars().peekable(),
|
||||
version: Version::One,
|
||||
};
|
||||
parser.parse_in_list()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use rustc_ast::ast;
|
|||
use rustc_span::{symbol::sym, Span};
|
||||
|
||||
use crate::config::{Config, GroupImportsTactic};
|
||||
use crate::imports::{normalize_use_trees_with_granularity, UseSegment, UseTree};
|
||||
use crate::imports::{normalize_use_trees_with_granularity, UseSegmentKind, UseTree};
|
||||
use crate::items::{is_mod_decl, rewrite_extern_crate, rewrite_mod};
|
||||
use crate::lists::{itemize_list, write_list, ListFormatting, ListItem};
|
||||
use crate::rewrite::RewriteContext;
|
||||
|
|
@ -182,16 +182,16 @@ fn group_imports(uts: Vec<UseTree>) -> Vec<Vec<UseTree>> {
|
|||
external_imports.push(ut);
|
||||
continue;
|
||||
}
|
||||
match &ut.path[0] {
|
||||
UseSegment::Ident(id, _) => match id.as_ref() {
|
||||
match &ut.path[0].kind {
|
||||
UseSegmentKind::Ident(id, _) => match id.as_ref() {
|
||||
"std" | "alloc" | "core" => std_imports.push(ut),
|
||||
_ => external_imports.push(ut),
|
||||
},
|
||||
UseSegment::Slf(_) | UseSegment::Super(_) | UseSegment::Crate(_) => {
|
||||
UseSegmentKind::Slf(_) | UseSegmentKind::Super(_) | UseSegmentKind::Crate(_) => {
|
||||
local_imports.push(ut)
|
||||
}
|
||||
// These are probably illegal here
|
||||
UseSegment::Glob | UseSegment::List(_) => external_imports.push(ut),
|
||||
UseSegmentKind::Glob | UseSegmentKind::List(_) => external_imports.push(ut),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue