about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNick Cameron <ncameron@mozilla.com>2017-06-06 12:19:54 +1200
committerNick Cameron <ncameron@mozilla.com>2017-06-12 14:14:23 +1200
commitcb7fcdd520d8297bbb2bea6e0a017d1b5df0b819 (patch)
treeb7f03cd9045e21d7ff7b25fdece0f4bd19d5ccb7
parent5ebb0e2498edc84093003d8053a7d11e51536120 (diff)
downloadrust-cb7fcdd520d8297bbb2bea6e0a017d1b5df0b819.tar.gz
rust-cb7fcdd520d8297bbb2bea6e0a017d1b5df0b819.zip
Impl and trait item sigs
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs45
-rw-r--r--src/librustc_save_analysis/lib.rs8
-rw-r--r--src/librustc_save_analysis/sig.rs152
3 files changed, 178 insertions, 27 deletions
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 61fc9a9adfb..ea346d99e31 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -392,13 +392,13 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
                       sig: &'l ast::MethodSig,
                       body: Option<&'l ast::Block>,
                       id: ast::NodeId,
-                      name: ast::Name,
+                      name: ast::Ident,
                       vis: Visibility,
                       attrs: &'l [Attribute],
                       span: Span) {
         debug!("process_method: {}:{}", id, name);
 
-        if let Some(method_data) = self.save_ctxt.get_method_data(id, name, span) {
+        if let Some(method_data) = self.save_ctxt.get_method_data(id, name.name, span) {
 
             let sig_str = ::make_signature(&sig.decl, &sig.generics);
             if body.is_some() {
@@ -424,7 +424,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
                             Some(id) => {
                                 for item in self.tcx.associated_items(id) {
                                     if item.kind == ty::AssociatedKind::Method {
-                                        if item.name == name {
+                                        if item.name == name.name {
                                             decl_id = Some(item.def_id);
                                             break;
                                         }
@@ -456,7 +456,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
                     parent: trait_id,
                     visibility: vis,
                     docs: docs_for_attrs(attrs),
-                    sig: method_data.sig,
+                    sig: sig::method_signature(id, name, sig, &self.save_ctxt),
                     attributes: attrs.to_vec(),
                 }.lower(self.tcx));
             }
@@ -581,13 +581,14 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
                            name: ast::Name,
                            span: Span,
                            typ: &'l ast::Ty,
-                           expr: &'l ast::Expr,
+                           expr: Option<&'l ast::Expr>,
                            parent_id: DefId,
                            vis: Visibility,
                            attrs: &'l [Attribute]) {
         let qualname = format!("::{}", self.tcx.node_path_str(id));
 
         let sub_span = self.span.sub_span_after_keyword(span, keywords::Const);
+        let value = expr.map(|e| self.span.snippet(e.span)).unwrap_or(String::new());
 
         if !self.span.filter_generated(sub_span, span) {
             self.dumper.variable(VariableData {
@@ -596,20 +597,22 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
                 id: id,
                 name: name.to_string(),
                 qualname: qualname,
-                value: self.span.snippet(expr.span),
+                value: value,
                 type_value: ty_to_string(&typ),
                 scope: self.cur_scope,
                 parent: Some(parent_id),
                 visibility: vis,
                 docs: docs_for_attrs(attrs),
-                sig: None,
+                sig: sig::assoc_const_signature(id, name, typ, expr, &self.save_ctxt),
                 attributes: attrs.to_vec(),
             }.lower(self.tcx));
         }
 
         // walk type and init value
         self.visit_ty(typ);
-        self.visit_expr(expr);
+        if let Some(expr) = expr {
+            self.visit_expr(expr);
+        }
     }
 
     // FIXME tuple structs should generate tuple-specific data.
@@ -1122,12 +1125,12 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
     fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId) {
         self.process_macro_use(trait_item.span, trait_item.id);
         match trait_item.node {
-            ast::TraitItemKind::Const(ref ty, Some(ref expr)) => {
+            ast::TraitItemKind::Const(ref ty, ref expr) => {
                 self.process_assoc_const(trait_item.id,
                                          trait_item.ident.name,
                                          trait_item.span,
                                          &ty,
-                                         &expr,
+                                         expr.as_ref().map(|e| &**e),
                                          trait_id,
                                          Visibility::Public,
                                          &trait_item.attrs);
@@ -1136,12 +1139,12 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
                 self.process_method(sig,
                                     body.as_ref().map(|x| &**x),
                                     trait_item.id,
-                                    trait_item.ident.name,
+                                    trait_item.ident,
                                     Visibility::Public,
                                     &trait_item.attrs,
                                     trait_item.span);
             }
-            ast::TraitItemKind::Type(ref _bounds, ref default_ty) => {
+            ast::TraitItemKind::Type(ref bounds, ref default_ty) => {
                 // FIXME do something with _bounds (for type refs)
                 let name = trait_item.ident.name.to_string();
                 let qualname = format!("::{}", self.tcx.node_path_str(trait_item.id));
@@ -1157,7 +1160,11 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
                         visibility: Visibility::Public,
                         parent: Some(trait_id),
                         docs: docs_for_attrs(&trait_item.attrs),
-                        sig: None,
+                        sig: sig::assoc_type_signature(trait_item.id,
+                                                       trait_item.ident,
+                                                       Some(bounds),
+                                                       default_ty.as_ref().map(|ty| &**ty),
+                                                       &self.save_ctxt),
                         attributes: trait_item.attrs.clone(),
                     }.lower(self.tcx));
                 }
@@ -1166,7 +1173,6 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
                     self.visit_ty(default_ty)
                 }
             }
-            ast::TraitItemKind::Const(ref ty, None) => self.visit_ty(ty),
             ast::TraitItemKind::Macro(_) => {}
         }
     }
@@ -1179,7 +1185,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
                                          impl_item.ident.name,
                                          impl_item.span,
                                          &ty,
-                                         &expr,
+                                         Some(expr),
                                          impl_id,
                                          From::from(&impl_item.vis),
                                          &impl_item.attrs);
@@ -1188,12 +1194,17 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
                 self.process_method(sig,
                                     Some(body),
                                     impl_item.id,
-                                    impl_item.ident.name,
+                                    impl_item.ident,
                                     From::from(&impl_item.vis),
                                     &impl_item.attrs,
                                     impl_item.span);
             }
-            ast::ImplItemKind::Type(ref ty) => self.visit_ty(ty),
+            ast::ImplItemKind::Type(ref ty) => {
+                // FIXME uses of the assoc type should ideally point to this
+                // 'def' and the name here should be a ref to the def in the
+                // trait.
+                self.visit_ty(ty)
+            }
             ast::ImplItemKind::Macro(_) => {}
         }
     }
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 8e280377ce2..4802494f08e 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -369,8 +369,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
 
     // FIXME would be nice to take a MethodItem here, but the ast provides both
     // trait and impl flavours, so the caller must do the disassembly.
-    pub fn get_method_data(&self, id: ast::NodeId,
-                           name: ast::Name, span: Span) -> Option<FunctionData> {
+    pub fn get_method_data(&self,
+                           id: ast::NodeId,
+                           name: ast::Name,
+                           span: Span)
+                           -> Option<FunctionData> {
         // The qualname for a method is the trait name or name of the struct in an impl in
         // which the method is declared in, followed by the method's name.
         let (qualname, parent_scope, decl_id, vis, docs, attributes) =
@@ -460,7 +463,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             visibility: vis,
             parent: parent_scope,
             docs: docs,
-            // TODO
             sig: None,
             attributes: attributes,
         })
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index b2a62038dfc..1d03ab1383a 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -14,7 +14,7 @@
 //
 // ```
 // fn foo(x: String) {
-//     println!("{}", x);   
+//     println!("{}", x);
 // }
 // ```
 // The signature string is something like "fn foo(x: String) {}" and the signature
@@ -63,6 +63,32 @@ pub fn variant_signature(variant: &ast::Variant, scx: &SaveContext) -> Option<Si
     variant.node.make(0, None, scx).ok()
 }
 
+pub fn method_signature(id: NodeId,
+                        ident: ast::Ident,
+                        m: &ast::MethodSig,
+                        scx: &SaveContext)
+                        -> Option<Signature> {
+    make_method_signature(id, ident, m, scx).ok()
+}
+
+pub fn assoc_const_signature(id: NodeId,
+                             ident: ast::Name,
+                             ty: &ast::Ty,
+                             default: Option<&ast::Expr>,
+                             scx: &SaveContext)
+                             -> Option<Signature> {
+    make_assoc_const_signature(id, ident, ty, default, scx).ok()
+}
+
+pub fn assoc_type_signature(id: NodeId,
+                            ident: ast::Ident,
+                            bounds: Option<&ast::TyParamBounds>,
+                            default: Option<&ast::Ty>,
+                            scx: &SaveContext)
+                            -> Option<Signature> {
+    make_assoc_type_signature(id, ident, bounds, default, scx).ok()
+}
+
 type Result = ::std::result::Result<Signature, &'static str>;
 
 trait Sig {
@@ -215,7 +241,7 @@ impl Sig for ast::Ty {
                     format!("<{} as {}>::", nested_ty.text, first)
                 } else {
                     // FIXME handle path instead of elipses.
-                    format!("<{} as ...>::", nested_ty.text)                    
+                    format!("<{} as ...>::", nested_ty.text)
                 };
 
                 let name = pprust::path_segment_to_string(path.segments.last().ok_or("Bad path")?);
@@ -263,7 +289,7 @@ impl Sig for ast::Ty {
             ast::TyKind::ImplicitSelf |
             ast::TyKind::Mac(_) => Err("Ty"),
         }
-    }    
+    }
 }
 
 impl Sig for ast::Item {
@@ -497,7 +523,7 @@ impl Sig for ast::Item {
 
                 let ty_sig = ty.make(offset + text.len(), id, scx)?;
                 text.push_str(&ty_sig.text);
-                
+
                 text.push_str(" {}");
 
                 Ok(merge_sigs(text, vec![generics_sig, trait_sig, ty_sig]))
@@ -582,7 +608,9 @@ impl Sig for ast::Generics {
 
             if !l.bounds.is_empty() {
                 l_text.push_str(": ");
-                let bounds = l.bounds.iter().map(|l| l.ident.to_string()).collect::<Vec<_>>().join(" + ");
+                let bounds = l.bounds.iter().map(|l| {
+                    l.ident.to_string()
+                }).collect::<Vec<_>>().join(" + ");
                 l_text.push_str(&bounds);
                 // FIXME add lifetime bounds refs.
             }
@@ -783,5 +811,115 @@ fn name_and_generics(mut text: String,
 }
 
 
-// TODO impl items, trait items
-// for impl/trait sigs - function for each kind, rather than use trait.
+fn make_assoc_type_signature(id: NodeId,
+                             ident: ast::Ident,
+                             bounds: Option<&ast::TyParamBounds>,
+                             default: Option<&ast::Ty>,
+                             scx: &SaveContext)
+                             -> Result {
+    let mut text = "type ".to_owned();
+    let name = ident.to_string();
+    let mut defs = vec![SigElement {
+        id: id_from_node_id(id, scx),
+        start: text.len(),
+        end: text.len() + name.len(),
+    }];
+    let mut refs = vec![];
+    text.push_str(&name);
+    if let Some(bounds) = bounds {
+        text.push_str(": ");
+        // FIXME should descend into bounds
+        text.push_str(&pprust::bounds_to_string(bounds));
+    }
+    if let Some(default) = default {
+        text.push_str(" = ");
+        let ty_sig = default.make(text.len(), Some(id), scx)?;
+        text.push_str(&ty_sig.text);
+        defs.extend(ty_sig.defs.into_iter());
+        refs.extend(ty_sig.refs.into_iter());
+    }
+    text.push(';');
+    Ok(Signature { text, defs, refs })
+}
+
+fn make_assoc_const_signature(id: NodeId,
+                              ident: ast::Name,
+                              ty: &ast::Ty,
+                              default: Option<&ast::Expr>,
+                              scx: &SaveContext)
+                              -> Result {
+    let mut text = "const ".to_owned();
+    let name = ident.to_string();
+    let mut defs = vec![SigElement {
+        id: id_from_node_id(id, scx),
+        start: text.len(),
+        end: text.len() + name.len(),
+    }];
+    let mut refs = vec![];
+    text.push_str(&name);
+    text.push_str(": ");
+
+    let ty_sig = ty.make(text.len(), Some(id), scx)?;
+    text.push_str(&ty_sig.text);
+    defs.extend(ty_sig.defs.into_iter());
+    refs.extend(ty_sig.refs.into_iter());
+
+    if let Some(default) = default {
+        text.push_str(" = ");
+        text.push_str(&pprust::expr_to_string(default));
+    }
+    text.push(';');
+    Ok(Signature { text, defs, refs })
+}
+
+fn make_method_signature(id: NodeId,
+                         ident: ast::Ident,
+                         m: &ast::MethodSig,
+                         scx: &SaveContext)
+                         -> Result {
+    // FIXME code dup with function signature
+    let mut text = String::new();
+    if m.constness.node == ast::Constness::Const {
+        text.push_str("const ");
+    }
+    if m.unsafety == ast::Unsafety::Unsafe {
+        text.push_str("unsafe ");
+    }
+    if m.abi != ::syntax::abi::Abi::Rust {
+        text.push_str("extern");
+        text.push_str(&m.abi.to_string());
+        text.push(' ');
+    }
+    text.push_str("fn ");
+
+    let mut sig = name_and_generics(text,
+                                    0,
+                                    &m.generics,
+                                    id,
+                                    ident,
+                                    scx)?;
+
+    sig.text.push('(');
+    for i in &m.decl.inputs {
+        // FIXME shoudl descend into patterns to add defs.
+        sig.text.push_str(&pprust::pat_to_string(&i.pat));
+        sig.text.push_str(": ");
+        let nested = i.ty.make(sig.text.len(), Some(i.id), scx)?;
+        sig.text.push_str(&nested.text);
+        sig.text.push(',');
+        sig.defs.extend(nested.defs.into_iter());
+        sig.refs.extend(nested.refs.into_iter());
+    }
+    sig.text.push(')');
+
+    if let ast::FunctionRetTy::Ty(ref t) = m.decl.output {
+        sig.text.push_str(" -> ");
+        let nested = t.make(sig.text.len(), None, scx)?;
+        sig.text.push_str(&nested.text);
+        sig.defs.extend(nested.defs.into_iter());
+        sig.refs.extend(nested.refs.into_iter());
+    }
+    sig.text.push_str(" {}");
+
+    Ok(sig)
+}