X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;ds=sidebyside;f=src%2Fimports.rs;h=0f635fe1ccb3584210a21debfaa5f423384f556a;hb=1e2258ffa949bf4d273259e78d326857c0b2bb3d;hp=9c914ce476ddd8a4a707a65e8fd9d5a2ad7be3ba;hpb=9f53665f91be16c9aa7afd83f7c79357fec9152b;p=rust.git diff --git a/src/imports.rs b/src/imports.rs index 9c914ce476d..0f635fe1ccb 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -2,8 +2,11 @@ use std::cmp::Ordering; use std::fmt; -use rustc_span::{source_map, symbol::sym, BytePos, Span, DUMMY_SP}; -use syntax::ast::{self, UseTreeKind}; +use rustc_ast::ast::{self, UseTreeKind}; +use rustc_span::{ + symbol::{self, sym}, + BytePos, Span, DUMMY_SP, +}; use crate::comment::combine_strs_with_missing_comments; use crate::config::lists::*; @@ -20,7 +23,7 @@ /// Returns a name imported by a `use` declaration. /// E.g., returns `Ordering` for `std::cmp::Ordering` and `self` for `std::cmp::self`. -pub(crate) fn path_to_imported_ident(path: &ast::Path) -> ast::Ident { +pub(crate) fn path_to_imported_ident(path: &ast::Path) -> symbol::Ident { path.segments.last().unwrap().ident } @@ -156,7 +159,7 @@ fn from_path_segment( } } -pub(crate) fn merge_use_trees(use_trees: Vec) -> Vec { +pub(crate) fn merge_use_trees(use_trees: Vec, merge_by: SharedPrefix) -> Vec { let mut result = Vec::with_capacity(use_trees.len()); for use_tree in use_trees { if use_tree.has_comment() || use_tree.attrs.is_some() { @@ -165,8 +168,11 @@ pub(crate) fn merge_use_trees(use_trees: Vec) -> Vec { } for flattened in use_tree.flatten() { - if let Some(tree) = result.iter_mut().find(|tree| tree.share_prefix(&flattened)) { - tree.merge(&flattened); + if let Some(tree) = result + .iter_mut() + .find(|tree| tree.share_prefix(&flattened, merge_by)) + { + tree.merge(&flattened, merge_by); } else { result.push(flattened); } @@ -175,6 +181,24 @@ pub(crate) fn merge_use_trees(use_trees: Vec) -> Vec { result } +pub(crate) fn flatten_use_trees(use_trees: Vec) -> Vec { + use_trees + .into_iter() + .flat_map(UseTree::flatten) + .map(|mut tree| { + // If a path ends in `::self`, rewrite it to `::{self}`. + if let Some(UseSegment::Slf(..)) = tree.path.last() { + let self_segment = tree.path.pop().unwrap(); + tree.path.push(UseSegment::List(vec![UseTree::from_path( + vec![self_segment], + DUMMY_SP, + )])); + } + tree + }) + .collect() +} + impl fmt::Debug for UseTree { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self, f) @@ -328,7 +352,7 @@ fn from_ast( }; let leading_modsep = - context.config.edition() == Edition::Edition2018 && a.prefix.is_global(); + context.config.edition() >= Edition::Edition2018 && a.prefix.is_global(); let mut modsep = leading_modsep; @@ -505,16 +529,16 @@ fn has_comment(&self) -> bool { fn same_visibility(&self, other: &UseTree) -> bool { match (&self.visibility, &other.visibility) { ( - Some(source_map::Spanned { - node: ast::VisibilityKind::Inherited, + Some(ast::Visibility { + kind: ast::VisibilityKind::Inherited, .. }), None, ) | ( None, - Some(source_map::Spanned { - node: ast::VisibilityKind::Inherited, + Some(ast::Visibility { + kind: ast::VisibilityKind::Inherited, .. }), ) @@ -524,7 +548,7 @@ fn same_visibility(&self, other: &UseTree) -> bool { } } - fn share_prefix(&self, other: &UseTree) -> bool { + fn share_prefix(&self, other: &UseTree, shared_prefix: SharedPrefix) -> bool { if self.path.is_empty() || other.path.is_empty() || self.attrs.is_some() @@ -532,7 +556,12 @@ fn share_prefix(&self, other: &UseTree) -> bool { { false } else { - self.path[0] == other.path[0] + match shared_prefix { + SharedPrefix::Crate => self.path[0] == other.path[0], + SharedPrefix::Module => { + self.path[..self.path.len() - 1] == other.path[..other.path.len() - 1] + } + } } } @@ -570,7 +599,7 @@ fn flatten(self) -> Vec { } } - fn merge(&mut self, other: &UseTree) { + fn merge(&mut self, other: &UseTree, merge_by: SharedPrefix) { let mut prefix = 0; for (a, b) in self.path.iter().zip(other.path.iter()) { if *a == *b { @@ -579,20 +608,30 @@ fn merge(&mut self, other: &UseTree) { break; } } - if let Some(new_path) = merge_rest(&self.path, &other.path, prefix) { + if let Some(new_path) = merge_rest(&self.path, &other.path, prefix, merge_by) { self.path = new_path; self.span = self.span.to(other.span); } } } -fn merge_rest(a: &[UseSegment], b: &[UseSegment], mut len: usize) -> Option> { +fn merge_rest( + a: &[UseSegment], + b: &[UseSegment], + mut len: usize, + merge_by: SharedPrefix, +) -> Option> { if a.len() == len && b.len() == len { return None; } if a.len() != len && b.len() != len { - if let UseSegment::List(mut list) = a[len].clone() { - merge_use_trees_inner(&mut list, UseTree::from_path(b[len..].to_vec(), DUMMY_SP)); + if let UseSegment::List(ref list) = a[len] { + let mut list = list.clone(); + merge_use_trees_inner( + &mut list, + UseTree::from_path(b[len..].to_vec(), DUMMY_SP), + merge_by, + ); let mut new_path = b[..len].to_vec(); new_path.push(UseSegment::List(list)); return Some(new_path); @@ -619,20 +658,20 @@ fn merge_rest(a: &[UseSegment], b: &[UseSegment], mut len: usize) -> Option, use_tree: UseTree) { - let similar_trees = trees.iter_mut().filter(|tree| tree.share_prefix(&use_tree)); - if use_tree.path.len() == 1 { +fn merge_use_trees_inner(trees: &mut Vec, use_tree: UseTree, merge_by: SharedPrefix) { + let similar_trees = trees + .iter_mut() + .filter(|tree| tree.share_prefix(&use_tree, merge_by)); + if use_tree.path.len() == 1 && merge_by == SharedPrefix::Crate { if let Some(tree) = similar_trees.min_by_key(|tree| tree.path.len()) { if tree.path.len() == 1 { return; } } - } else { - if let Some(tree) = similar_trees.max_by_key(|tree| tree.path.len()) { - if tree.path.len() > 1 { - tree.merge(&use_tree); - return; - } + } else if let Some(tree) = similar_trees.max_by_key(|tree| tree.path.len()) { + if tree.path.len() > 1 { + tree.merge(&use_tree, merge_by); + return; } } trees.push(use_tree); @@ -845,6 +884,12 @@ fn rewrite(&self, context: &RewriteContext<'_>, mut shape: Shape) -> Option { - assert_eq!( - merge_use_trees(parse_use_trees!($($input,)*)), - parse_use_trees!($($output,)*), - ); - } + macro_rules! test_merge { + ($by:ident, [$($input:expr),* $(,)*], [$($output:expr),* $(,)*]) => { + assert_eq!( + merge_use_trees(parse_use_trees!($($input,)*), SharedPrefix::$by), + parse_use_trees!($($output,)*), + ); } + } - test_merge!(["a::b::{c, d}", "a::b::{e, f}"], ["a::b::{c, d, e, f}"]); - test_merge!(["a::b::c", "a::b"], ["a::{b, b::c}"]); - test_merge!(["a::b", "a::b"], ["a::b"]); - test_merge!(["a", "a::b", "a::b::c"], ["a::{self, b, b::c}"]); + #[test] + fn test_use_tree_merge_crate() { test_merge!( + Crate, + ["a::b::{c, d}", "a::b::{e, f}"], + ["a::b::{c, d, e, f}"] + ); + test_merge!(Crate, ["a::b::c", "a::b"], ["a::{b, b::c}"]); + test_merge!(Crate, ["a::b", "a::b"], ["a::b"]); + test_merge!(Crate, ["a", "a::b", "a::b::c"], ["a::{self, b, b::c}"]); + test_merge!( + Crate, ["a", "a::b", "a::b::c", "a::b::c::d"], ["a::{self, b, b::{c, c::d}}"] ); - test_merge!(["a", "a::b", "a::b::c", "a::b"], ["a::{self, b, b::c}"]); test_merge!( + Crate, + ["a", "a::b", "a::b::c", "a::b"], + ["a::{self, b, b::c}"] + ); + test_merge!( + Crate, ["a::{b::{self, c}, d::e}", "a::d::f"], ["a::{b::{self, c}, d::{e, f}}"] ); test_merge!( + Crate, ["a::d::f", "a::{b::{self, c}, d::e}"], ["a::{b::{self, c}, d::{e, f}}"] ); test_merge!( + Crate, ["a::{c, d, b}", "a::{d, e, b, a, f}", "a::{f, g, c}"], ["a::{a, b, c, d, e, f, g}"] ); test_merge!( + Crate, ["a::{self}", "b::{self as foo}"], ["a::{self}", "b::{self as foo}"] ); } + #[test] + fn test_use_tree_merge_module() { + test_merge!( + Module, + ["foo::b", "foo::{a, c, d::e}"], + ["foo::{a, b, c}", "foo::d::e"] + ); + + test_merge!( + Module, + ["foo::{a::b, a::c, d::e, d::f}"], + ["foo::a::{b, c}", "foo::d::{e, f}"] + ); + } + + #[test] + fn test_flatten_use_trees() { + assert_eq!( + flatten_use_trees(parse_use_trees!["foo::{a::{b, c}, d::e}"]), + parse_use_trees!["foo::a::b", "foo::a::c", "foo::d::e"] + ); + + assert_eq!( + flatten_use_trees(parse_use_trees!["foo::{self, a, b::{c, d}, e::*}"]), + parse_use_trees![ + "foo::{self}", + "foo::a", + "foo::b::c", + "foo::b::d", + "foo::e::*" + ] + ); + } + #[test] fn test_use_tree_flatten() { assert_eq!(