summary refs log tree commit diff
path: root/src/librustc_save_analysis
diff options
context:
space:
mode:
authorPietro Albini <pietro@pietroalbini.org>2017-09-26 23:04:00 +0200
committerPietro Albini <pietro@pietroalbini.org>2017-11-30 13:10:26 +0100
commit91ba8b42fcce0491fa8a1b95e4088bcabf9abf4a (patch)
tree8816e095bc7a534e8d9ecbe542a5e640d35b6c2c /src/librustc_save_analysis
parentd6b010f98beae1591ea6e8e21008de97d6cf5be4 (diff)
downloadrust-91ba8b42fcce0491fa8a1b95e4088bcabf9abf4a.tar.gz
rust-91ba8b42fcce0491fa8a1b95e4088bcabf9abf4a.zip
Implement RFC 2128 (use_nested_groups)
This commit adds support for nested groups inside `use` declarations,
such as `use foo::{bar, sub::{baz::Foo, *}};`.
Diffstat (limited to 'src/librustc_save_analysis')
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs188
1 files changed, 107 insertions, 81 deletions
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index d4257e35823..602c70f9a1f 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -38,7 +38,7 @@ use syntax::symbol::keywords;
 use syntax::visit::{self, Visitor};
 use syntax::print::pprust::{bounds_to_string, generics_to_string, path_to_string, ty_to_string};
 use syntax::ptr::P;
-use syntax::codemap::Spanned;
+use syntax::codemap::{Spanned, DUMMY_SP};
 use syntax_pos::*;
 
 use {escape, generated_code, lower_attributes, PathCollector, SaveContext};
@@ -1229,6 +1229,106 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
             ast::ImplItemKind::Macro(_) => {}
         }
     }
+
+    fn process_use_tree(&mut self,
+                         use_tree: &'l ast::UseTree,
+                         id: NodeId,
+                         parent_item: &'l ast::Item,
+                         prefix: &ast::Path) {
+        let path = &use_tree.prefix;
+        let access = access_from!(self.save_ctxt, parent_item);
+
+        match use_tree.kind {
+            ast::UseTreeKind::Simple(ident) => {
+                let path = ast::Path {
+                    segments: prefix.segments
+                        .iter()
+                        .chain(path.segments.iter())
+                        .cloned()
+                        .collect(),
+                    span: path.span,
+                };
+
+                let sub_span = self.span.span_for_last_ident(path.span);
+                let mod_id = match self.lookup_def_id(id) {
+                    Some(def_id) => {
+                        self.process_def_kind(id, path.span, sub_span, def_id);
+                        Some(def_id)
+                    }
+                    None => None,
+                };
+
+                // 'use' always introduces an alias, if there is not an explicit
+                // one, there is an implicit one.
+                let sub_span = match self.span.sub_span_after_keyword(use_tree.span,
+                                                                      keywords::As) {
+                    Some(sub_span) => Some(sub_span),
+                    None => sub_span,
+                };
+
+                if !self.span.filter_generated(sub_span, path.span) {
+                    let span =
+                        self.span_from_span(sub_span.expect("No span found for use"));
+                    self.dumper.import(&access, Import {
+                        kind: ImportKind::Use,
+                        ref_id: mod_id.map(|id| ::id_from_def_id(id)),
+                        span,
+                        name: ident.to_string(),
+                        value: String::new(),
+                    });
+                }
+                self.write_sub_paths_truncated(&path);
+            }
+            ast::UseTreeKind::Glob => {
+                let path = ast::Path {
+                    segments: prefix.segments
+                        .iter()
+                        .chain(path.segments.iter())
+                        .cloned()
+                        .collect(),
+                    span: path.span,
+                };
+
+                // Make a comma-separated list of names of imported modules.
+                let mut names = vec![];
+                let glob_map = &self.save_ctxt.analysis.glob_map;
+                let glob_map = glob_map.as_ref().unwrap();
+                if glob_map.contains_key(&id) {
+                    for n in glob_map.get(&id).unwrap() {
+                        names.push(n.to_string());
+                    }
+                }
+
+                let sub_span = self.span.sub_span_of_token(use_tree.span,
+                                                           token::BinOp(token::Star));
+                if !self.span.filter_generated(sub_span, use_tree.span) {
+                    let span =
+                        self.span_from_span(sub_span.expect("No span found for use glob"));
+                    self.dumper.import(&access, Import {
+                        kind: ImportKind::GlobUse,
+                        ref_id: None,
+                        span,
+                        name: "*".to_owned(),
+                        value: names.join(", "),
+                    });
+                }
+                self.write_sub_paths(&path);
+            }
+            ast::UseTreeKind::Nested(ref nested_items) => {
+                let prefix = ast::Path {
+                    segments: prefix.segments
+                        .iter()
+                        .chain(path.segments.iter())
+                        .cloned()
+                        .collect(),
+                    span: path.span,
+                };
+                for &(ref tree, id) in nested_items {
+                    self.process_use_tree(tree, id, parent_item, &prefix);
+                }
+            }
+        }
+    }
 }
 
 impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, O> {
@@ -1275,86 +1375,12 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
         use syntax::ast::ItemKind::*;
         self.process_macro_use(item.span);
         match item.node {
-            Use(ref use_item) => {
-                let access = access_from!(self.save_ctxt, item);
-
-                match use_item.node {
-                    ast::ViewPathSimple(ident, ref path) => {
-                        let sub_span = self.span.span_for_last_ident(path.span);
-                        let mod_id = match self.lookup_def_id(item.id) {
-                            Some(def_id) => {
-                                self.process_def_kind(item.id, path.span, sub_span, def_id);
-                                Some(def_id)
-                            }
-                            None => None,
-                        };
-
-                        // 'use' always introduces an alias, if there is not an explicit
-                        // one, there is an implicit one.
-                        let sub_span = match self.span
-                            .sub_span_after_keyword(use_item.span, keywords::As)
-                        {
-                            Some(sub_span) => Some(sub_span),
-                            None => sub_span,
-                        };
-
-                        if !self.span.filter_generated(sub_span, path.span) {
-                            let span =
-                                self.span_from_span(sub_span.expect("No span found for use"));
-                            self.dumper.import(
-                                &access,
-                                Import {
-                                    kind: ImportKind::Use,
-                                    ref_id: mod_id.map(|id| ::id_from_def_id(id)),
-                                    span,
-                                    name: ident.to_string(),
-                                    value: String::new(),
-                                },
-                            );
-                        }
-                        self.write_sub_paths_truncated(path);
-                    }
-                    ast::ViewPathGlob(ref path) => {
-                        // Make a comma-separated list of names of imported modules.
-                        let mut names = vec![];
-                        let glob_map = &self.save_ctxt.analysis.glob_map;
-                        let glob_map = glob_map.as_ref().unwrap();
-                        if glob_map.contains_key(&item.id) {
-                            for n in glob_map.get(&item.id).unwrap() {
-                                names.push(n.to_string());
-                            }
-                        }
-
-                        let sub_span = self.span
-                            .sub_span_of_token(item.span, token::BinOp(token::Star));
-                        if !self.span.filter_generated(sub_span, item.span) {
-                            let span =
-                                self.span_from_span(sub_span.expect("No span found for use glob"));
-                            self.dumper.import(
-                                &access,
-                                Import {
-                                    kind: ImportKind::GlobUse,
-                                    ref_id: None,
-                                    span,
-                                    name: "*".to_owned(),
-                                    value: names.join(", "),
-                                },
-                            );
-                        }
-                        self.write_sub_paths(path);
-                    }
-                    ast::ViewPathList(ref path, ref list) => {
-                        for plid in list {
-                            let id = plid.node.id;
-                            if let Some(def_id) = self.lookup_def_id(id) {
-                                let span = plid.span;
-                                self.process_def_kind(id, span, Some(span), def_id);
-                            }
-                        }
-
-                        self.write_sub_paths(path);
-                    }
-                }
+            Use(ref use_tree) => {
+                let prefix = ast::Path {
+                    segments: vec![],
+                    span: DUMMY_SP,
+                };
+                self.process_use_tree(use_tree, item.id, item, &prefix);
             }
             ExternCrate(_) => {
                 let alias_span = self.span.span_for_last_ident(item.span);