]> git.lizzy.rs Git - rust.git/commitdiff
save-analysis: give better text info in value fields
authorNick Cameron <ncameron@mozilla.com>
Wed, 11 May 2016 20:46:39 +0000 (13:46 -0700)
committerNick Cameron <ncameron@mozilla.com>
Wed, 11 May 2016 20:50:23 +0000 (13:50 -0700)
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/json_dumper.rs
src/librustc_save_analysis/lib.rs
src/libsyntax/ast.rs

index 6f84ccc9e36d4ed2e2e9ee3ce7686222674de641..4d79ddfe8cbe30773d94043ab9975e8299202c43 100644 (file)
@@ -39,7 +39,7 @@
 use syntax::codemap::*;
 use syntax::parse::token::{self, keywords};
 use syntax::visit::{self, Visitor};
-use syntax::print::pprust::{path_to_string, ty_to_string};
+use syntax::print::pprust::{path_to_string, ty_to_string, bounds_to_string, generics_to_string};
 use syntax::ptr::P;
 
 use super::{escape, generated_code, SaveContext, PathCollector};
@@ -388,9 +388,12 @@ fn process_method(&mut self,
 
         if let Some(method_data) = self.save_ctxt.get_method_data(id, name, span) {
 
+            let sig_str = ::make_signature(&sig.decl, &sig.generics);
             if body.is_some() {
                 if !self.span.filter_generated(Some(method_data.span), span) {
-                    self.dumper.function(method_data.clone().lower(self.tcx));
+                    let mut data = method_data.clone();
+                    data.value = sig_str;
+                    self.dumper.function(data.lower(self.tcx));
                 }
                 self.process_formals(&sig.decl.inputs, &method_data.qualname);
             } else {
@@ -401,7 +404,7 @@ fn process_method(&mut self,
                         span: method_data.span,
                         scope: method_data.scope,
                         qualname: method_data.qualname.clone(),
-                        value: String::new(), // TODO
+                        value: sig_str,
                     }.lower(self.tcx));
                 }
             }
@@ -540,19 +543,33 @@ fn process_const(&mut self,
         self.visit_expr(expr);
     }
 
+    // FIXME tuple structs should generate tuple-specific data.
     fn process_struct(&mut self,
                       item: &ast::Item,
                       def: &ast::VariantData,
                       ty_params: &ast::Generics) {
+        let name = item.ident.to_string();
         let qualname = format!("::{}", self.tcx.node_path_str(item.id));
 
-        let val = self.span.snippet(item.span);
         let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Struct);
+        let val = if let ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) =
+                    item.node {
+            let fields_str = fields.iter()
+                                   .enumerate()
+                                   .map(|(i, f)| f.ident.map(|i| i.to_string())
+                                                  .unwrap_or(i.to_string()))
+                                   .collect::<Vec<_>>()
+                                   .join(", ");
+            format!("{} {{ {} }}", name, fields_str)
+        } else {
+            String::new()
+        };
+
         if !self.span.filter_generated(sub_span, item.span) {
             self.dumper.struct_data(StructData {
                 span: sub_span.expect("No span found for struct"),
                 id: item.id,
-                name: item.ident.to_string(),
+                name: name,
                 ctor_id: def.id(),
                 qualname: qualname.clone(),
                 scope: self.cur_scope,
@@ -589,11 +606,17 @@ fn process_enum(&mut self,
             let mut qualname = enum_data.qualname.clone();
             qualname.push_str("::");
             qualname.push_str(&name);
-            let val = self.span.snippet(variant.span);
 
             match variant.node.data {
-                ast::VariantData::Struct(..) => {
+                ast::VariantData::Struct(ref fields, _) => {
                     let sub_span = self.span.span_for_first_ident(variant.span);
+                    let fields_str = fields.iter()
+                                           .enumerate()
+                                           .map(|(i, f)| f.ident.map(|i| i.to_string())
+                                                          .unwrap_or(i.to_string()))
+                                           .collect::<Vec<_>>()
+                                           .join(", ");
+                    let val = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str);
                     if !self.span.filter_generated(sub_span, variant.span) {
                         self.dumper.struct_variant(StructVariantData {
                             span: sub_span.expect("No span found for struct variant"),
@@ -606,13 +629,22 @@ fn process_enum(&mut self,
                         }.lower(self.tcx));
                     }
                 }
-                _ => {
+                ref v => {
                     let sub_span = self.span.span_for_first_ident(variant.span);
+                    let mut val = format!("{}::{}", enum_data.name, name);
+                    if let &ast::VariantData::Tuple(ref fields, _) = v {
+                        val.push('(');
+                        val.push_str(&fields.iter()
+                                            .map(|f| ty_to_string(&f.ty))
+                                            .collect::<Vec<_>>()
+                                            .join(", "));
+                        val.push(')');
+                    }
                     if !self.span.filter_generated(sub_span, variant.span) {
                         self.dumper.tuple_variant(TupleVariantData {
                             span: sub_span.expect("No span found for tuple variant"),
                             id: variant.node.data.id(),
-                            name: name.to_string(),
+                            name: name,
                             qualname: qualname,
                             type_value: enum_data.qualname.clone(),
                             value: val,
@@ -678,14 +710,22 @@ fn process_trait(&mut self,
                      generics: &ast::Generics,
                      trait_refs: &ast::TyParamBounds,
                      methods: &[ast::TraitItem]) {
+        let name = item.ident.to_string();
         let qualname = format!("::{}", self.tcx.node_path_str(item.id));
-        let val = self.span.snippet(item.span);
+        let mut val = name.clone();
+        if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() {
+            val.push_str(&generics_to_string(generics));
+        }
+        if !trait_refs.is_empty() {
+            val.push_str(": ");
+            val.push_str(&bounds_to_string(trait_refs));
+        }
         let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Trait);
         if !self.span.filter_generated(sub_span, item.span) {
             self.dumper.trait_data(TraitData {
                 span: sub_span.expect("No span found for trait"),
                 id: item.id,
-                name: item.ident.to_string(),
+                name: name,
                 qualname: qualname.clone(),
                 scope: self.cur_scope,
                 value: val
@@ -915,13 +955,15 @@ fn process_var_decl(&mut self, p: &ast::Pat, value: String) {
         self.visit_pat(&p);
 
         for &(id, ref p, immut, _) in &collector.collected_paths {
-            let value = if immut == ast::Mutability::Immutable {
+            let mut value = if immut == ast::Mutability::Immutable {
                 value.to_string()
             } else {
                 "<mutable>".to_string()
             };
             let types = self.tcx.node_types();
             let typ = types.get(&id).map(|t| t.to_string()).unwrap_or(String::new());
+            value.push_str(": ");
+            value.push_str(&typ);
             // Get the span only for the name of the variable (I hope the path
             // is only ever a variable name, but who knows?).
             let sub_span = self.span.span_for_last_ident(p.span);
@@ -1283,13 +1325,13 @@ fn visit_expr(&mut self, ex: &ast::Expr) {
             }
             ast::ExprKind::ForLoop(ref pattern, ref subexpression, ref block, _) |
             ast::ExprKind::WhileLet(ref pattern, ref subexpression, ref block, _) => {
-                let value = self.span.snippet(mk_sp(ex.span.lo, subexpression.span.hi));
+                let value = self.span.snippet(subexpression.span);
                 self.process_var_decl(pattern, value);
                 visit::walk_expr(self, subexpression);
                 visit::walk_block(self, block);
             }
             ast::ExprKind::IfLet(ref pattern, ref subexpression, ref block, ref opt_else) => {
-                let value = self.span.snippet(mk_sp(ex.span.lo, subexpression.span.hi));
+                let value = self.span.snippet(subexpression.span);
                 self.process_var_decl(pattern, value);
                 visit::walk_expr(self, subexpression);
                 visit::walk_block(self, block);
@@ -1379,7 +1421,7 @@ fn visit_stmt(&mut self, s: &ast::Stmt) {
 
     fn visit_local(&mut self, l: &ast::Local) {
         self.process_macro_use(l.span, l.id);
-        let value = self.span.snippet(l.span);
+        let value = l.init.as_ref().map(|i| self.span.snippet(i.span)).unwrap_or(String::new());
         self.process_var_decl(&l.pat, value);
 
         // Just walk the initialiser and type (don't want to walk the pattern again).
index 156a6f5cc971d2a33ee9c9761e2612f46fcc47c8..bdbecdd1d5341b2cea841aa9d7b700c260d7cab4 100644 (file)
@@ -167,17 +167,17 @@ struct Def {
 
 #[derive(Debug, RustcEncodable)]
 enum DefKind {
-    // value = type + generics
+    // value = variant names
     Enum,
-    // value = type + generics
+    // value = enum name + variant name + types
     Tuple,
-    // value = type + generics + types
+    // value = [enum name +] name + fields
     Struct,
-    // value = type + generics
+    // value = signature
     Trait,
     // value = type + generics
     Function,
-    // No id
+    // No id, no value.
     Macro,
     // value = file_name
     Mod,
@@ -186,8 +186,6 @@ enum DefKind {
     // value = type and init expression
     Variable,
 }
-// TODO value for function and method
-// TODO none of the values are right.
 
 impl From<EnumData> for Def {
     fn from(data: EnumData) -> Def {
index 0a5ac3af7140a1472114ba8ab5499ce192c92195..8c00a5699939824f2f1882c94d1ef66ada74d37b 100644 (file)
@@ -52,7 +52,7 @@
 use syntax::codemap::*;
 use syntax::parse::token::{self, keywords};
 use syntax::visit::{self, Visitor};
-use syntax::print::pprust::ty_to_string;
+use syntax::print::pprust::{ty_to_string, arg_to_string};
 
 pub use self::csv_dumper::CsvDumper;
 pub use self::json_dumper::JsonDumper;
@@ -122,11 +122,13 @@ pub fn get_external_crates(&self) -> Vec<CrateData> {
 
     pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
         match item.node {
-            ast::ItemKind::Fn(..) => {
+            ast::ItemKind::Fn(ref decl, _, _, _, ref generics, _) => {
                 let name = self.tcx.node_path_str(item.id);
                 let qualname = format!("::{}", name);
                 let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Fn);
                 filter!(self.span_utils, sub_span, item.span, None);
+
+
                 Some(Data::FunctionData(FunctionData {
                     id: item.id,
                     name: name,
@@ -134,7 +136,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     declaration: None,
                     span: sub_span.unwrap(),
                     scope: self.enclosing_scope(item.id),
-                    value: String::new(), // TODO
+                    value: make_signature(decl, generics),
                 }))
             }
             ast::ItemKind::Static(ref typ, mt, ref expr) => {
@@ -191,17 +193,22 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     filename: filename,
                 }))
             }
-            ast::ItemKind::Enum(..) => {
-                let enum_name = format!("::{}", self.tcx.node_path_str(item.id));
-                let val = self.span_utils.snippet(item.span);
+            ast::ItemKind::Enum(ref def, _) => {
+                let name = item.ident.to_string();
+                let qualname = format!("::{}", self.tcx.node_path_str(item.id));
                 let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Enum);
                 filter!(self.span_utils, sub_span, item.span, None);
+                let variants_str = def.variants.iter()
+                                      .map(|v| v.node.name.to_string())
+                                      .collect::<Vec<_>>()
+                                      .join(", ");
+                let val = format!("{}::{{{}}}", name, variants_str);
                 Some(Data::EnumData(EnumData {
                     id: item.id,
-                    name: item.ident.to_string(),
+                    name: name,
                     value: val,
                     span: sub_span.unwrap(),
-                    qualname: enum_name,
+                    qualname: qualname,
                     scope: self.enclosing_scope(item.id),
                 }))
             }
@@ -355,7 +362,8 @@ pub fn get_method_data(&self, id: ast::NodeId,
             declaration: decl_id,
             span: sub_span.unwrap(),
             scope: self.enclosing_scope(id),
-            value: String::new(), // TODO
+            // FIXME you get better data here by using the visitor.
+            value: String::new(),
         })
     }
 
@@ -640,6 +648,35 @@ pub fn enclosing_scope(&self, id: NodeId) -> NodeId {
     }
 }
 
+fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String {
+    let mut sig = String::new();
+    if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() {
+        sig.push('<');
+        sig.push_str(&generics.lifetimes.iter()
+                              .map(|l| l.lifetime.name.to_string())
+                              .collect::<Vec<_>>()
+                              .join(", "));
+        if !generics.lifetimes.is_empty() {
+            sig.push_str(", ");
+        }
+        sig.push_str(&generics.ty_params.iter()
+                              .map(|l| l.ident.to_string())
+                              .collect::<Vec<_>>()
+                              .join(", "));
+        sig.push_str("> ");
+    }
+    sig.push('(');
+    sig.push_str(&decl.inputs.iter().map(arg_to_string).collect::<Vec<_>>().join(", "));
+    sig.push(')');
+    match decl.output {
+        ast::FunctionRetTy::None(_) => sig.push_str(" -> !"),
+        ast::FunctionRetTy::Default(_) => {}
+        ast::FunctionRetTy::Ty(ref t) => sig.push_str(&format!(" -> {}", ty_to_string(t))),
+    }
+
+    sig
+}
+
 // An AST visitor for collecting paths from patterns.
 struct PathCollector {
     // The Row field identifies the kind of pattern.
index d1ad330c58ce88f4830d1d71e4657797f3172e8d..e9f3472c4a10ca4edc8b8bd87d5e5ea97aae0cc5 100644 (file)
@@ -2030,10 +2030,7 @@ pub enum ItemKind {
     /// A struct definition, e.g. `struct Foo<A> {x: A}`
     Struct(VariantData, Generics),
     /// Represents a Trait Declaration
-    Trait(Unsafety,
-              Generics,
-              TyParamBounds,
-              Vec<TraitItem>),
+    Trait(Unsafety, Generics, TyParamBounds, Vec<TraitItem>),
 
     // Default trait implementations
     ///