Skip to content

Commit 3e14f01

Browse files
committed
save-analysis: give better text info in value fields
1 parent a0a9877 commit 3e14f01

File tree

4 files changed

+109
-35
lines changed

4 files changed

+109
-35
lines changed

src/librustc_save_analysis/dump_visitor.rs

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use syntax::ast::{self, NodeId, PatKind};
3939
use syntax::codemap::*;
4040
use syntax::parse::token::{self, keywords};
4141
use syntax::visit::{self, Visitor};
42-
use syntax::print::pprust::{path_to_string, ty_to_string};
42+
use syntax::print::pprust::{path_to_string, ty_to_string, bounds_to_string, generics_to_string};
4343
use syntax::ptr::P;
4444

4545
use super::{escape, generated_code, SaveContext, PathCollector};
@@ -388,9 +388,12 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
388388

389389
if let Some(method_data) = self.save_ctxt.get_method_data(id, name, span) {
390390

391+
let sig_str = ::make_signature(&sig.decl, &sig.generics);
391392
if body.is_some() {
392393
if !self.span.filter_generated(Some(method_data.span), span) {
393-
self.dumper.function(method_data.clone().lower(self.tcx));
394+
let mut data = method_data.clone();
395+
data.value = sig_str;
396+
self.dumper.function(data.lower(self.tcx));
394397
}
395398
self.process_formals(&sig.decl.inputs, &method_data.qualname);
396399
} else {
@@ -401,7 +404,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
401404
span: method_data.span,
402405
scope: method_data.scope,
403406
qualname: method_data.qualname.clone(),
404-
value: String::new(), // TODO
407+
value: sig_str,
405408
}.lower(self.tcx));
406409
}
407410
}
@@ -540,19 +543,33 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
540543
self.visit_expr(expr);
541544
}
542545

546+
// FIXME tuple structs should generate tuple-specific data.
543547
fn process_struct(&mut self,
544548
item: &ast::Item,
545549
def: &ast::VariantData,
546550
ty_params: &ast::Generics) {
551+
let name = item.ident.to_string();
547552
let qualname = format!("::{}", self.tcx.node_path_str(item.id));
548553

549-
let val = self.span.snippet(item.span);
550554
let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Struct);
555+
let val = if let ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) =
556+
item.node {
557+
let fields_str = fields.iter()
558+
.enumerate()
559+
.map(|(i, f)| f.ident.map(|i| i.to_string())
560+
.unwrap_or(i.to_string()))
561+
.collect::<Vec<_>>()
562+
.join(", ");
563+
format!("{} {{ {} }}", name, fields_str)
564+
} else {
565+
String::new()
566+
};
567+
551568
if !self.span.filter_generated(sub_span, item.span) {
552569
self.dumper.struct_data(StructData {
553570
span: sub_span.expect("No span found for struct"),
554571
id: item.id,
555-
name: item.ident.to_string(),
572+
name: name,
556573
ctor_id: def.id(),
557574
qualname: qualname.clone(),
558575
scope: self.cur_scope,
@@ -589,11 +606,17 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
589606
let mut qualname = enum_data.qualname.clone();
590607
qualname.push_str("::");
591608
qualname.push_str(&name);
592-
let val = self.span.snippet(variant.span);
593609

594610
match variant.node.data {
595-
ast::VariantData::Struct(..) => {
611+
ast::VariantData::Struct(ref fields, _) => {
596612
let sub_span = self.span.span_for_first_ident(variant.span);
613+
let fields_str = fields.iter()
614+
.enumerate()
615+
.map(|(i, f)| f.ident.map(|i| i.to_string())
616+
.unwrap_or(i.to_string()))
617+
.collect::<Vec<_>>()
618+
.join(", ");
619+
let val = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str);
597620
if !self.span.filter_generated(sub_span, variant.span) {
598621
self.dumper.struct_variant(StructVariantData {
599622
span: sub_span.expect("No span found for struct variant"),
@@ -606,13 +629,22 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
606629
}.lower(self.tcx));
607630
}
608631
}
609-
_ => {
632+
ref v => {
610633
let sub_span = self.span.span_for_first_ident(variant.span);
634+
let mut val = format!("{}::{}", enum_data.name, name);
635+
if let &ast::VariantData::Tuple(ref fields, _) = v {
636+
val.push('(');
637+
val.push_str(&fields.iter()
638+
.map(|f| ty_to_string(&f.ty))
639+
.collect::<Vec<_>>()
640+
.join(", "));
641+
val.push(')');
642+
}
611643
if !self.span.filter_generated(sub_span, variant.span) {
612644
self.dumper.tuple_variant(TupleVariantData {
613645
span: sub_span.expect("No span found for tuple variant"),
614646
id: variant.node.data.id(),
615-
name: name.to_string(),
647+
name: name,
616648
qualname: qualname,
617649
type_value: enum_data.qualname.clone(),
618650
value: val,
@@ -678,14 +710,22 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
678710
generics: &ast::Generics,
679711
trait_refs: &ast::TyParamBounds,
680712
methods: &[ast::TraitItem]) {
713+
let name = item.ident.to_string();
681714
let qualname = format!("::{}", self.tcx.node_path_str(item.id));
682-
let val = self.span.snippet(item.span);
715+
let mut val = name.clone();
716+
if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() {
717+
val.push_str(&generics_to_string(generics));
718+
}
719+
if !trait_refs.is_empty() {
720+
val.push_str(": ");
721+
val.push_str(&bounds_to_string(trait_refs));
722+
}
683723
let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Trait);
684724
if !self.span.filter_generated(sub_span, item.span) {
685725
self.dumper.trait_data(TraitData {
686726
span: sub_span.expect("No span found for trait"),
687727
id: item.id,
688-
name: item.ident.to_string(),
728+
name: name,
689729
qualname: qualname.clone(),
690730
scope: self.cur_scope,
691731
value: val
@@ -915,13 +955,15 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
915955
self.visit_pat(&p);
916956

917957
for &(id, ref p, immut, _) in &collector.collected_paths {
918-
let value = if immut == ast::Mutability::Immutable {
958+
let mut value = if immut == ast::Mutability::Immutable {
919959
value.to_string()
920960
} else {
921961
"<mutable>".to_string()
922962
};
923963
let types = self.tcx.node_types();
924964
let typ = types.get(&id).map(|t| t.to_string()).unwrap_or(String::new());
965+
value.push_str(": ");
966+
value.push_str(&typ);
925967
// Get the span only for the name of the variable (I hope the path
926968
// is only ever a variable name, but who knows?).
927969
let sub_span = self.span.span_for_last_ident(p.span);
@@ -1283,13 +1325,13 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
12831325
}
12841326
ast::ExprKind::ForLoop(ref pattern, ref subexpression, ref block, _) |
12851327
ast::ExprKind::WhileLet(ref pattern, ref subexpression, ref block, _) => {
1286-
let value = self.span.snippet(mk_sp(ex.span.lo, subexpression.span.hi));
1328+
let value = self.span.snippet(subexpression.span);
12871329
self.process_var_decl(pattern, value);
12881330
visit::walk_expr(self, subexpression);
12891331
visit::walk_block(self, block);
12901332
}
12911333
ast::ExprKind::IfLet(ref pattern, ref subexpression, ref block, ref opt_else) => {
1292-
let value = self.span.snippet(mk_sp(ex.span.lo, subexpression.span.hi));
1334+
let value = self.span.snippet(subexpression.span);
12931335
self.process_var_decl(pattern, value);
12941336
visit::walk_expr(self, subexpression);
12951337
visit::walk_block(self, block);
@@ -1379,7 +1421,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
13791421

13801422
fn visit_local(&mut self, l: &ast::Local) {
13811423
self.process_macro_use(l.span, l.id);
1382-
let value = self.span.snippet(l.span);
1424+
let value = l.init.as_ref().map(|i| self.span.snippet(i.span)).unwrap_or(String::new());
13831425
self.process_var_decl(&l.pat, value);
13841426

13851427
// Just walk the initialiser and type (don't want to walk the pattern again).

src/librustc_save_analysis/json_dumper.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,17 +167,17 @@ struct Def {
167167

168168
#[derive(Debug, RustcEncodable)]
169169
enum DefKind {
170-
// value = type + generics
170+
// value = variant names
171171
Enum,
172-
// value = type + generics
172+
// value = enum name + variant name + types
173173
Tuple,
174-
// value = type + generics + types
174+
// value = [enum name +] name + fields
175175
Struct,
176-
// value = type + generics
176+
// value = signature
177177
Trait,
178178
// value = type + generics
179179
Function,
180-
// No id
180+
// No id, no value.
181181
Macro,
182182
// value = file_name
183183
Mod,
@@ -186,8 +186,6 @@ enum DefKind {
186186
// value = type and init expression
187187
Variable,
188188
}
189-
// TODO value for function and method
190-
// TODO none of the values are right.
191189

192190
impl From<EnumData> for Def {
193191
fn from(data: EnumData) -> Def {

src/librustc_save_analysis/lib.rs

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ use syntax::ast::{self, NodeId, PatKind};
5252
use syntax::codemap::*;
5353
use syntax::parse::token::{self, keywords};
5454
use syntax::visit::{self, Visitor};
55-
use syntax::print::pprust::ty_to_string;
55+
use syntax::print::pprust::{ty_to_string, arg_to_string};
5656

5757
pub use self::csv_dumper::CsvDumper;
5858
pub use self::json_dumper::JsonDumper;
@@ -122,19 +122,21 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
122122

123123
pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
124124
match item.node {
125-
ast::ItemKind::Fn(..) => {
125+
ast::ItemKind::Fn(ref decl, _, _, _, ref generics, _) => {
126126
let name = self.tcx.node_path_str(item.id);
127127
let qualname = format!("::{}", name);
128128
let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Fn);
129129
filter!(self.span_utils, sub_span, item.span, None);
130+
131+
130132
Some(Data::FunctionData(FunctionData {
131133
id: item.id,
132134
name: name,
133135
qualname: qualname,
134136
declaration: None,
135137
span: sub_span.unwrap(),
136138
scope: self.enclosing_scope(item.id),
137-
value: String::new(), // TODO
139+
value: make_signature(decl, generics),
138140
}))
139141
}
140142
ast::ItemKind::Static(ref typ, mt, ref expr) => {
@@ -191,17 +193,22 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
191193
filename: filename,
192194
}))
193195
}
194-
ast::ItemKind::Enum(..) => {
195-
let enum_name = format!("::{}", self.tcx.node_path_str(item.id));
196-
let val = self.span_utils.snippet(item.span);
196+
ast::ItemKind::Enum(ref def, _) => {
197+
let name = item.ident.to_string();
198+
let qualname = format!("::{}", self.tcx.node_path_str(item.id));
197199
let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Enum);
198200
filter!(self.span_utils, sub_span, item.span, None);
201+
let variants_str = def.variants.iter()
202+
.map(|v| v.node.name.to_string())
203+
.collect::<Vec<_>>()
204+
.join(", ");
205+
let val = format!("{}::{{{}}}", name, variants_str);
199206
Some(Data::EnumData(EnumData {
200207
id: item.id,
201-
name: item.ident.to_string(),
208+
name: name,
202209
value: val,
203210
span: sub_span.unwrap(),
204-
qualname: enum_name,
211+
qualname: qualname,
205212
scope: self.enclosing_scope(item.id),
206213
}))
207214
}
@@ -355,7 +362,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
355362
declaration: decl_id,
356363
span: sub_span.unwrap(),
357364
scope: self.enclosing_scope(id),
358-
value: String::new(), // TODO
365+
// FIXME you get better data here by using the visitor.
366+
value: String::new(),
359367
})
360368
}
361369

@@ -640,6 +648,35 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
640648
}
641649
}
642650

651+
fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String {
652+
let mut sig = String::new();
653+
if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() {
654+
sig.push('<');
655+
sig.push_str(&generics.lifetimes.iter()
656+
.map(|l| l.lifetime.name.to_string())
657+
.collect::<Vec<_>>()
658+
.join(", "));
659+
if !generics.lifetimes.is_empty() {
660+
sig.push_str(", ");
661+
}
662+
sig.push_str(&generics.ty_params.iter()
663+
.map(|l| l.ident.to_string())
664+
.collect::<Vec<_>>()
665+
.join(", "));
666+
sig.push_str("> ");
667+
}
668+
sig.push('(');
669+
sig.push_str(&decl.inputs.iter().map(arg_to_string).collect::<Vec<_>>().join(", "));
670+
sig.push(')');
671+
match decl.output {
672+
ast::FunctionRetTy::None(_) => sig.push_str(" -> !"),
673+
ast::FunctionRetTy::Default(_) => {}
674+
ast::FunctionRetTy::Ty(ref t) => sig.push_str(&format!(" -> {}", ty_to_string(t))),
675+
}
676+
677+
sig
678+
}
679+
643680
// An AST visitor for collecting paths from patterns.
644681
struct PathCollector {
645682
// The Row field identifies the kind of pattern.

src/libsyntax/ast.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2030,10 +2030,7 @@ pub enum ItemKind {
20302030
/// A struct definition, e.g. `struct Foo<A> {x: A}`
20312031
Struct(VariantData, Generics),
20322032
/// Represents a Trait Declaration
2033-
Trait(Unsafety,
2034-
Generics,
2035-
TyParamBounds,
2036-
Vec<TraitItem>),
2033+
Trait(Unsafety, Generics, TyParamBounds, Vec<TraitItem>),
20372034

20382035
// Default trait implementations
20392036
///

0 commit comments

Comments
 (0)