]> git.lizzy.rs Git - rust.git/commitdiff
save-analysis: index extern blocks
authorNick Cameron <ncameron@mozilla.com>
Wed, 8 Mar 2017 05:04:30 +0000 (18:04 +1300)
committerNick Cameron <ncameron@mozilla.com>
Tue, 4 Apr 2017 03:56:47 +0000 (15:56 +1200)
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/lib.rs
src/test/run-make/save-analysis-fail/foo.rs

index 491618f7952d8af3f5f6105d55ccfbc621da876f..3fd0ce45e3610af20760a82c093a76450a1f6e9d 100644 (file)
@@ -1599,4 +1599,39 @@ fn visit_local(&mut self, l: &'l ast::Local) {
         walk_list!(self, visit_ty, &l.ty);
         walk_list!(self, visit_expr, &l.init);
     }
+
+    fn visit_foreign_item(&mut self, item: &'l ast::ForeignItem) {
+        match item.node {
+            ast::ForeignItemKind::Fn(ref decl, ref generics) => {
+                if let Some(fn_data) = self.save_ctxt.get_extern_item_data(item) {
+                    down_cast_data!(fn_data, FunctionData, item.span);
+                    if !self.span.filter_generated(Some(fn_data.span), item.span) {
+                        self.dumper.function(fn_data.clone().lower(self.tcx));
+                    }
+
+                    self.nest_tables(item.id, |v| v.process_formals(&decl.inputs,
+                                                                    &fn_data.qualname));
+                    self.process_generic_params(generics, item.span, &fn_data.qualname, item.id);
+                }
+
+                for arg in &decl.inputs {
+                    self.visit_ty(&arg.ty);
+                }
+
+                if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output {
+                    self.visit_ty(&ret_ty);
+                }
+            }
+            ast::ForeignItemKind::Static(ref ty, _) => {
+                if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
+                    down_cast_data!(var_data, VariableData, item.span);
+                    if !self.span.filter_generated(Some(var_data.span), item.span) {
+                        self.dumper.variable(var_data.lower(self.tcx));
+                    }
+                }
+
+                self.visit_ty(ty);
+            }
+        }
+    }
 }
index 1de9fbc8e4941f04e02d2de4c226c714050f7a31..b34cffd2d15bdb46e479cdfce2d59586dddbf801 100644 (file)
@@ -120,6 +120,46 @@ pub fn get_external_crates(&self) -> Vec<CrateData> {
         result
     }
 
+    pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
+        let qualname = format!("::{}", self.tcx.node_path_str(item.id));
+        match item.node {
+            ast::ForeignItemKind::Fn(ref decl, ref generics) => {
+                let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Fn);
+                Some(Data::FunctionData(FunctionData {
+                    id: item.id,
+                    name: item.ident.to_string(),
+                    qualname: qualname,
+                    declaration: None,
+                    span: sub_span.unwrap(),
+                    scope: self.enclosing_scope(item.id),
+                    value: make_signature(decl, generics),
+                    visibility: From::from(&item.vis),
+                    parent: None,
+                    docs: docs_for_attrs(&item.attrs),
+                    sig: self.sig_base_extern(item),
+                }))
+            }
+            ast::ForeignItemKind::Static(ref ty, m) => {
+                let keyword = if m { keywords::Mut } else { keywords::Static };
+                let sub_span = self.span_utils.sub_span_after_keyword(item.span, keyword);
+                Some(Data::VariableData(VariableData {
+                    id: item.id,
+                    kind: VariableKind::Static,
+                    name: item.ident.to_string(),
+                    qualname: qualname,
+                    span: sub_span.unwrap(),
+                    scope: self.enclosing_scope(item.id),
+                    parent: None,
+                    value: String::new(),
+                    type_value: ty_to_string(ty),
+                    visibility: From::from(&item.vis),
+                    docs: docs_for_attrs(&item.attrs),
+                    sig: Some(self.sig_base_extern(item)),
+                }))
+            }
+        }
+    }
+
     pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
         match item.node {
             ast::ItemKind::Fn(ref decl, .., ref generics, _) => {
@@ -751,6 +791,21 @@ fn sig_base(&self, item: &ast::Item) -> Signature {
         }
     }
 
+    fn sig_base_extern(&self, item: &ast::ForeignItem) -> Signature {
+        let text = self.span_utils.signature_string_for_span(item.span);
+        let name = item.ident.to_string();
+        let ident_start = text.find(&name).expect("Name not in signature?");
+        let ident_end = ident_start + name.len();
+        Signature {
+            span: mk_sp(item.span.lo, item.span.lo + BytePos(text.len() as u32)),
+            text: text,
+            ident_start: ident_start,
+            ident_end: ident_end,
+            defs: vec![],
+            refs: vec![],
+        }
+    }
+
     #[inline]
     pub fn enclosing_scope(&self, id: NodeId) -> NodeId {
         self.tcx.hir.get_enclosing_scope(id).unwrap_or(CRATE_NODE_ID)
index e331f65abb7b3200edb7fb16a5c8c7b55ef95bf5..a996aa4fad5a7c247e0791430489ed8e61bdf4c3 100644 (file)
@@ -448,3 +448,8 @@ fn test_format_args() {
     print!("{0} + {} = {}", x, y);
     print!("x is {}, y is {1}, name is {n}", x, y, n = name);
 }
+
+extern {
+    static EXTERN_FOO: u8;
+    fn extern_foo(a: u8, b: i32) -> String;
+}