1
Fork 0

AST: Make renames in imports closer to the source

Fix `unused_import_braces` lint false positive on `use prefix::{self as rename}`
This commit is contained in:
Vadim Petrochenkov 2018-03-09 18:58:44 +03:00
parent c6c6cf9515
commit b057c554ab
12 changed files with 53 additions and 40 deletions

View file

@ -2047,8 +2047,8 @@ impl<'a> LoweringContext<'a> {
let path = &tree.prefix;
match tree.kind {
UseTreeKind::Simple(ident) => {
*name = ident.name;
UseTreeKind::Simple(rename) => {
*name = tree.ident().name;
// First apply the prefix to the path
let mut path = Path {
@ -2064,7 +2064,7 @@ impl<'a> LoweringContext<'a> {
if path.segments.len() > 1 &&
path.segments.last().unwrap().identifier.name == keywords::SelfValue.name() {
let _ = path.segments.pop();
if ident.name == keywords::SelfValue.name() {
if rename.is_none() {
*name = path.segments.last().unwrap().identifier.name;
}
}

View file

@ -377,11 +377,12 @@ impl UnusedImportBraces {
// Trigger the lint if the nested item is a non-self single item
let node_ident;
match items[0].0.kind {
ast::UseTreeKind::Simple(ident) => {
if ident.name == keywords::SelfValue.name() {
ast::UseTreeKind::Simple(rename) => {
let orig_ident = items[0].0.prefix.segments.last().unwrap().identifier;
if orig_ident.name == keywords::SelfValue.name() {
return;
} else {
node_ident = ident;
node_ident = rename.unwrap_or(orig_ident);
}
}
ast::UseTreeKind::Glob => {

View file

@ -119,7 +119,8 @@ impl<'a> Resolver<'a> {
.collect();
match use_tree.kind {
ast::UseTreeKind::Simple(mut ident) => {
ast::UseTreeKind::Simple(rename) => {
let mut ident = use_tree.ident();
let mut source = module_path.pop().unwrap().node;
let mut type_ns_only = false;
@ -142,7 +143,7 @@ impl<'a> Resolver<'a> {
// Replace `use foo::self;` with `use foo;`
let _ = module_path.pop();
source = last_segment.node;
if ident.name == keywords::SelfValue.name() {
if rename.is_none() {
ident = last_segment.node;
}
}
@ -162,7 +163,7 @@ impl<'a> Resolver<'a> {
ModuleKind::Block(..) => unreachable!(),
};
source.name = crate_name;
if ident.name == keywords::DollarCrate.name() {
if rename.is_none() {
ident.name = crate_name;
}
@ -206,8 +207,8 @@ impl<'a> Resolver<'a> {
// Ensure there is at most one `self` in the list
let self_spans = items.iter().filter_map(|&(ref use_tree, _)| {
if let ast::UseTreeKind::Simple(ident) = use_tree.kind {
if ident.name == keywords::SelfValue.name() {
if let ast::UseTreeKind::Simple(..) = use_tree.kind {
if use_tree.ident().name == keywords::SelfValue.name() {
return Some(use_tree.span);
}
}

View file

@ -1342,7 +1342,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
.map(::id_from_def_id);
match use_tree.kind {
ast::UseTreeKind::Simple(ident) => {
ast::UseTreeKind::Simple(..) => {
let ident = use_tree.ident();
let path = ast::Path {
segments: prefix.segments
.iter()

View file

@ -1880,18 +1880,29 @@ pub type Variant = Spanned<Variant_>;
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum UseTreeKind {
Simple(Ident),
Glob,
Simple(Option<Ident>),
Nested(Vec<(UseTree, NodeId)>),
Glob,
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct UseTree {
pub kind: UseTreeKind,
pub prefix: Path,
pub kind: UseTreeKind,
pub span: Span,
}
impl UseTree {
pub fn ident(&self) -> Ident {
match self.kind {
UseTreeKind::Simple(Some(rename)) => rename,
UseTreeKind::Simple(None) =>
self.prefix.segments.last().expect("empty prefix in a simple import").identifier,
_ => panic!("`UseTree::ident` can only be used on a simple import"),
}
}
}
/// Distinguishes between Attributes that decorate items and Attributes that
/// are contained as statements within items. These two cases need to be
/// distinguished for pretty-printing.

View file

@ -294,7 +294,7 @@ pub trait AstBuilder {
vis: ast::Visibility, vp: P<ast::UseTree>) -> P<ast::Item>;
fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P<ast::Item>;
fn item_use_simple_(&self, sp: Span, vis: ast::Visibility,
ident: ast::Ident, path: ast::Path) -> P<ast::Item>;
ident: Option<ast::Ident>, path: ast::Path) -> P<ast::Item>;
fn item_use_list(&self, sp: Span, vis: ast::Visibility,
path: Vec<ast::Ident>, imports: &[ast::Ident]) -> P<ast::Item>;
fn item_use_glob(&self, sp: Span,
@ -1159,16 +1159,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
}
fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P<ast::Item> {
let last = path.segments.last().unwrap().identifier;
self.item_use_simple_(sp, vis, last, path)
self.item_use_simple_(sp, vis, None, path)
}
fn item_use_simple_(&self, sp: Span, vis: ast::Visibility,
ident: ast::Ident, path: ast::Path) -> P<ast::Item> {
rename: Option<ast::Ident>, path: ast::Path) -> P<ast::Item> {
self.item_use(sp, vis, P(ast::UseTree {
span: sp,
prefix: path,
kind: ast::UseTreeKind::Simple(ident),
kind: ast::UseTreeKind::Simple(rename),
}))
}
@ -1178,7 +1177,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
(ast::UseTree {
span: sp,
prefix: self.path(sp, vec![*id]),
kind: ast::UseTreeKind::Simple(*id),
kind: ast::UseTreeKind::Simple(None),
}, ast::DUMMY_NODE_ID)
}).collect();

View file

@ -323,7 +323,8 @@ pub fn noop_fold_use_tree<T: Folder>(use_tree: UseTree, fld: &mut T) -> UseTree
span: fld.new_span(use_tree.span),
prefix: fld.fold_path(use_tree.prefix),
kind: match use_tree.kind {
UseTreeKind::Simple(ident) => UseTreeKind::Simple(fld.fold_ident(ident)),
UseTreeKind::Simple(rename) =>
UseTreeKind::Simple(rename.map(|ident| fld.fold_ident(ident))),
UseTreeKind::Glob => UseTreeKind::Glob,
UseTreeKind::Nested(items) => UseTreeKind::Nested(items.move_map(|(tree, id)| {
(fld.fold_use_tree(tree), fld.new_id(id))

View file

@ -7033,9 +7033,7 @@ impl<'a> Parser<'a> {
}
} else {
// `use path::foo;` or `use path::foo as bar;`
let rename = self.parse_rename()?.
unwrap_or(prefix.segments.last().unwrap().identifier);
UseTreeKind::Simple(rename)
UseTreeKind::Simple(self.parse_rename()?)
}
};

View file

@ -2949,13 +2949,12 @@ impl<'a> State<'a> {
pub fn print_use_tree(&mut self, tree: &ast::UseTree) -> io::Result<()> {
match tree.kind {
ast::UseTreeKind::Simple(ref ident) => {
ast::UseTreeKind::Simple(rename) => {
self.print_path(&tree.prefix, false, 0, true)?;
if tree.prefix.segments.last().unwrap().identifier.name != ident.name {
if let Some(rename) = rename {
self.s.space()?;
self.word_space("as")?;
self.print_ident(*ident)?;
self.print_ident(rename)?;
}
}
ast::UseTreeKind::Glob => {

View file

@ -78,7 +78,7 @@ pub fn modify_for_testing(sess: &ParseSess,
span_diagnostic: &errors::Handler,
features: &Features) -> ast::Crate {
// Check for #[reexport_test_harness_main = "some_name"] which
// creates a `use some_name = __test::main;`. This needs to be
// creates a `use __test::main as some_name;`. This needs to be
// unconditional, so that the attribute is still marked as used in
// non-test builds.
let reexport_test_harness_main =
@ -240,7 +240,8 @@ fn mk_reexport_mod(cx: &mut TestCtxt,
cx.ext_cx.path(DUMMY_SP, vec![super_, r]))
}).chain(tested_submods.into_iter().map(|(r, sym)| {
let path = cx.ext_cx.path(DUMMY_SP, vec![super_, r, sym]);
cx.ext_cx.item_use_simple_(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public), r, path)
cx.ext_cx.item_use_simple_(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public),
Some(r), path)
})).collect();
let reexport_mod = ast::Mod {
@ -502,7 +503,7 @@ fn mk_std(cx: &TestCtxt) -> P<ast::Item> {
(ast::ItemKind::Use(P(ast::UseTree {
span: DUMMY_SP,
prefix: path_node(vec![id_test]),
kind: ast::UseTreeKind::Simple(id_test),
kind: ast::UseTreeKind::Simple(None),
})),
ast::VisibilityKind::Public, keywords::Invalid.ident())
} else {
@ -590,13 +591,13 @@ fn mk_test_module(cx: &mut TestCtxt) -> (P<ast::Item>, Option<P<ast::Item>>) {
tokens: None,
})).pop().unwrap();
let reexport = cx.reexport_test_harness_main.map(|s| {
// building `use <ident> = __test::main`
let reexport_ident = Ident::with_empty_ctxt(s);
// building `use __test::main as <ident>;`
let rename = Ident::with_empty_ctxt(s);
let use_path = ast::UseTree {
span: DUMMY_SP,
prefix: path_node(vec![mod_ident, Ident::from_str("main")]),
kind: ast::UseTreeKind::Simple(reexport_ident),
kind: ast::UseTreeKind::Simple(Some(rename)),
};
expander.fold_item(P(ast::Item {

View file

@ -354,10 +354,11 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(
visitor: &mut V, use_tree: &'a UseTree, id: NodeId,
) {
visitor.visit_path(&use_tree.prefix, id);
match use_tree.kind {
UseTreeKind::Simple(ident) => {
visitor.visit_ident(use_tree.span, ident);
UseTreeKind::Simple(rename) => {
if let Some(rename) = rename {
visitor.visit_ident(use_tree.span, rename);
}
}
UseTreeKind::Glob => {},
UseTreeKind::Nested(ref use_trees) => {

View file

@ -9,12 +9,12 @@
// except according to those terms.
#![deny(unused_import_braces)]
#![allow(dead_code)]
#![allow(unused_imports)]
use test::{A}; //~ ERROR braces around A is unnecessary
mod test {
use test::{self}; // OK
use test::{self as rename}; // OK
pub struct A;
}