提交 b057c554 编写于 作者: V Vadim Petrochenkov

AST: Make renames in imports closer to the source

Fix `unused_import_braces` lint false positive on `use prefix::{self as rename}`
上级 c6c6cf95
......@@ -2047,8 +2047,8 @@ fn lower_use_tree(&mut self,
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 @@ fn lower_use_tree(&mut self,
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;
}
}
......
......@@ -377,11 +377,12 @@ fn check_use_tree(&self, cx: &EarlyContext, use_tree: &ast::UseTree, item: &ast:
// 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 => {
......
......@@ -119,7 +119,8 @@ fn build_reduced_graph_for_use_tree(&mut self,
.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 @@ fn build_reduced_graph_for_use_tree(&mut self,
// 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 @@ fn build_reduced_graph_for_use_tree(&mut self,
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 @@ fn build_reduced_graph_for_use_tree(&mut self,
// 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);
}
}
......
......@@ -1342,7 +1342,8 @@ fn process_use_tree(&mut self,
.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()
......
......@@ -1880,18 +1880,29 @@ pub struct 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.
......
......@@ -294,7 +294,7 @@ fn item_use(&self, sp: Span,
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 @@ fn item_use(&self, sp: Span,
}
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 @@ fn item_use_list(&self, sp: Span, vis: ast::Visibility,
(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();
......
......@@ -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))
......
......@@ -7033,9 +7033,7 @@ fn parse_use_tree(&mut self, nested: bool) -> PResult<'a, UseTree> {
}
} 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()?)
}
};
......
......@@ -2949,13 +2949,12 @@ pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause)
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 => {
......
......@@ -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 {
......
......@@ -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) => {
......
......@@ -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;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册