Skip to content

Commit 5a6ca7a

Browse files
committed
save-analysis: add Signature info to structs
1 parent c217ab6 commit 5a6ca7a

File tree

6 files changed

+139
-6
lines changed

6 files changed

+139
-6
lines changed

src/librustc_save_analysis/data.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ pub struct StructData {
290290
pub fields: Vec<NodeId>,
291291
pub visibility: Visibility,
292292
pub docs: String,
293+
pub sig: Signature,
293294
}
294295

295296
#[derive(Debug, RustcEncodable)]
@@ -405,3 +406,28 @@ pub struct VariableRefData {
405406
pub scope: NodeId,
406407
pub ref_id: DefId,
407408
}
409+
410+
411+
/// Encodes information about the signature of a definition. This should have
412+
/// enough information to create a nice display about a definition without
413+
/// access to the source code.
414+
#[derive(Debug, RustcEncodable)]
415+
pub struct Signature {
416+
pub span: Span,
417+
pub text: String,
418+
// These identify the main identifier for the defintion as byte offsets into
419+
// `text`. E.g., of `foo` in `pub fn foo(...)`
420+
pub ident_start: usize,
421+
pub ident_end: usize,
422+
pub defs: Vec<SigElement>,
423+
pub refs: Vec<SigElement>,
424+
}
425+
426+
/// An element of a signature. `start` and `end` are byte offsets into the `text`
427+
/// of the parent `Signature`.
428+
#[derive(Debug, RustcEncodable)]
429+
pub struct SigElement {
430+
pub id: DefId,
431+
pub start: usize,
432+
pub end: usize,
433+
}

src/librustc_save_analysis/dump_visitor.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
619619
};
620620

621621
if !self.span.filter_generated(sub_span, item.span) {
622+
let mut sig = self.sig_base(item);
623+
sig.ident_start = sig.text.find(&name).expect("Name not in struct signature?");
624+
sig.ident_end = sig.ident_start + name.len();
622625
self.dumper.struct_data(StructData {
623626
span: sub_span.expect("No span found for struct"),
624627
id: item.id,
@@ -630,11 +633,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
630633
fields: fields,
631634
visibility: From::from(&item.vis),
632635
docs: docs_for_attrs(&item.attrs),
636+
sig: sig,
633637
}.lower(self.tcx));
634638
}
635639

636-
637-
// fields
638640
for field in def.fields() {
639641
self.process_struct_field_def(field, item.id);
640642
self.visit_ty(&field.ty);
@@ -643,6 +645,18 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
643645
self.process_generic_params(ty_params, item.span, &qualname, item.id);
644646
}
645647

648+
fn sig_base(&self, item: &ast::Item) -> Signature {
649+
let text = self.span.signature_string_for_span(item.span).expect("Couldn't make signature");
650+
Signature {
651+
span: mk_sp(item.span.lo, item.span.lo + BytePos(text.len() as u32)),
652+
text: text,
653+
ident_start: 0,
654+
ident_end: 0,
655+
defs: vec![],
656+
refs: vec![],
657+
}
658+
}
659+
646660
fn process_enum(&mut self,
647661
item: &'l ast::Item,
648662
enum_definition: &'l ast::EnumDef,

src/librustc_save_analysis/external_data.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use syntax::ast::NodeId;
1515
use syntax::codemap::CodeMap;
1616
use syntax_pos::Span;
1717

18-
use data::{self, Visibility};
18+
use data::{self, Visibility, SigElement};
1919

2020
// FIXME: this should be pub(crate), but the current snapshot doesn't allow it yet
2121
pub trait Lower {
@@ -428,6 +428,7 @@ pub struct StructData {
428428
pub fields: Vec<DefId>,
429429
pub visibility: Visibility,
430430
pub docs: String,
431+
pub sig: Signature,
431432
}
432433

433434
impl Lower for data::StructData {
@@ -445,6 +446,7 @@ impl Lower for data::StructData {
445446
fields: self.fields.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(),
446447
visibility: self.visibility,
447448
docs: self.docs,
449+
sig: self.sig.lower(tcx),
448450
}
449451
}
450452
}
@@ -700,3 +702,30 @@ impl Lower for data::VariableRefData {
700702
}
701703
}
702704
}
705+
706+
#[derive(Debug, RustcEncodable)]
707+
pub struct Signature {
708+
pub span: SpanData,
709+
pub text: String,
710+
// These identify the main identifier for the defintion as byte offsets into
711+
// `text`. E.g., of `foo` in `pub fn foo(...)`
712+
pub ident_start: usize,
713+
pub ident_end: usize,
714+
pub defs: Vec<SigElement>,
715+
pub refs: Vec<SigElement>,
716+
}
717+
718+
impl Lower for data::Signature {
719+
type Target = Signature;
720+
721+
fn lower(self, tcx: TyCtxt) -> Signature {
722+
Signature {
723+
span: SpanData::from_span(self.span, tcx.sess.codemap()),
724+
text: self.text,
725+
ident_start: self.ident_start,
726+
ident_end: self.ident_end,
727+
defs: self.defs,
728+
refs: self.refs,
729+
}
730+
}
731+
}

src/librustc_save_analysis/json_api_dumper.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ struct Def {
179179
children: Vec<Id>,
180180
decl_id: Option<Id>,
181181
docs: String,
182+
sig: Option<Signature>,
182183
}
183184

184185
#[derive(Debug, RustcEncodable)]
@@ -221,6 +222,7 @@ impl From<EnumData> for Option<Def> {
221222
children: data.variants.into_iter().map(|id| From::from(id)).collect(),
222223
decl_id: None,
223224
docs: data.docs,
225+
sig: None,
224226
}),
225227
_ => None,
226228
}
@@ -240,6 +242,7 @@ impl From<TupleVariantData> for Option<Def> {
240242
children: vec![],
241243
decl_id: None,
242244
docs: data.docs,
245+
sig: None,
243246
})
244247
}
245248
}
@@ -256,6 +259,7 @@ impl From<StructVariantData> for Option<Def> {
256259
children: vec![],
257260
decl_id: None,
258261
docs: data.docs,
262+
sig: None,
259263
})
260264
}
261265
}
@@ -273,6 +277,7 @@ impl From<StructData> for Option<Def> {
273277
children: data.fields.into_iter().map(|id| From::from(id)).collect(),
274278
decl_id: None,
275279
docs: data.docs,
280+
sig: Some(data.sig),
276281
}),
277282
_ => None,
278283
}
@@ -292,6 +297,7 @@ impl From<TraitData> for Option<Def> {
292297
parent: None,
293298
decl_id: None,
294299
docs: data.docs,
300+
sig: None,
295301
}),
296302
_ => None,
297303
}
@@ -311,6 +317,7 @@ impl From<FunctionData> for Option<Def> {
311317
parent: data.parent.map(|id| From::from(id)),
312318
decl_id: None,
313319
docs: data.docs,
320+
sig: None,
314321
}),
315322
_ => None,
316323
}
@@ -330,6 +337,7 @@ impl From<MethodData> for Option<Def> {
330337
parent: data.parent.map(|id| From::from(id)),
331338
decl_id: data.decl_id.map(|id| From::from(id)),
332339
docs: data.docs,
340+
sig: None,
333341
}),
334342
_ => None,
335343
}
@@ -348,6 +356,7 @@ impl From<MacroData> for Option<Def> {
348356
parent: None,
349357
decl_id: None,
350358
docs: data.docs,
359+
sig: None,
351360
})
352361
}
353362
}
@@ -365,6 +374,7 @@ impl From<ModData> for Option<Def> {
365374
parent: None,
366375
decl_id: None,
367376
docs: data.docs,
377+
sig: None,
368378
}),
369379
_ => None,
370380
}
@@ -384,6 +394,7 @@ impl From<TypeDefData> for Option<Def> {
384394
parent: data.parent.map(|id| From::from(id)),
385395
decl_id: None,
386396
docs: String::new(),
397+
sig: None,
387398
}),
388399
_ => None,
389400
}
@@ -408,6 +419,7 @@ impl From<VariableData> for Option<Def> {
408419
parent: data.parent.map(|id| From::from(id)),
409420
decl_id: None,
410421
docs: data.docs,
422+
sig: None,
411423
}),
412424
_ => None,
413425
}

src/librustc_save_analysis/json_dumper.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ impl<'b, W: Write + 'b> Dump for JsonDumper<'b, W> {
8686
children: data.items.into_iter().map(|id| From::from(id)).collect(),
8787
decl_id: None,
8888
docs: data.docs,
89+
sig: None,
8990
};
9091
if def.span.file_name != def.value {
9192
// If the module is an out-of-line defintion, then we'll make the
@@ -223,6 +224,7 @@ struct Def {
223224
children: Vec<Id>,
224225
decl_id: Option<Id>,
225226
docs: String,
227+
sig: Option<Signature>,
226228
}
227229

228230
#[derive(Debug, RustcEncodable)]
@@ -264,6 +266,7 @@ impl From<EnumData> for Def {
264266
children: data.variants.into_iter().map(|id| From::from(id)).collect(),
265267
decl_id: None,
266268
docs: data.docs,
269+
sig: None,
267270
}
268271
}
269272
}
@@ -280,6 +283,7 @@ impl From<TupleVariantData> for Def {
280283
children: vec![],
281284
decl_id: None,
282285
docs: data.docs,
286+
sig: None,
283287
}
284288
}
285289
}
@@ -295,6 +299,7 @@ impl From<StructVariantData> for Def {
295299
children: vec![],
296300
decl_id: None,
297301
docs: data.docs,
302+
sig: None,
298303
}
299304
}
300305
}
@@ -310,6 +315,7 @@ impl From<StructData> for Def {
310315
children: data.fields.into_iter().map(|id| From::from(id)).collect(),
311316
decl_id: None,
312317
docs: data.docs,
318+
sig: Some(data.sig),
313319
}
314320
}
315321
}
@@ -325,6 +331,7 @@ impl From<TraitData> for Def {
325331
children: data.items.into_iter().map(|id| From::from(id)).collect(),
326332
decl_id: None,
327333
docs: data.docs,
334+
sig: None,
328335
}
329336
}
330337
}
@@ -340,6 +347,7 @@ impl From<FunctionData> for Def {
340347
children: vec![],
341348
decl_id: None,
342349
docs: data.docs,
350+
sig: None,
343351
}
344352
}
345353
}
@@ -355,6 +363,7 @@ impl From<MethodData> for Def {
355363
children: vec![],
356364
decl_id: data.decl_id.map(|id| From::from(id)),
357365
docs: data.docs,
366+
sig: None,
358367
}
359368
}
360369
}
@@ -370,10 +379,10 @@ impl From<MacroData> for Def {
370379
children: vec![],
371380
decl_id: None,
372381
docs: data.docs,
382+
sig: None,
373383
}
374384
}
375385
}
376-
377386
impl From<TypeDefData> for Def {
378387
fn from(data: TypeDefData) -> Def {
379388
Def {
@@ -386,6 +395,7 @@ impl From<TypeDefData> for Def {
386395
children: vec![],
387396
decl_id: None,
388397
docs: String::new(),
398+
sig: None,
389399
}
390400
}
391401
}
@@ -406,6 +416,7 @@ impl From<VariableData> for Def {
406416
children: vec![],
407417
decl_id: None,
408418
docs: data.docs,
419+
sig: None,
409420
}
410421
}
411422
}

src/librustc_save_analysis/span_utils.rs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ use std::path::Path;
1818

1919
use syntax::ast;
2020
use syntax::parse::lexer::{self, Reader, StringReader};
21-
use syntax::parse::token::{self, Token};
22-
use syntax::symbol::keywords;
21+
use syntax::tokenstream::TokenTree;
2322
use syntax_pos::*;
2423

2524
#[derive(Clone)]
@@ -87,6 +86,12 @@ impl<'a> SpanUtils<'a> {
8786
lexer::StringReader::new(s.diagnostic(), filemap)
8887
}
8988

89+
fn span_to_tts(&self, span: Span) -> Vec<TokenTree> {
90+
let srdr = self.retokenise_span(span);
91+
let mut p = Parser::new(&self.sess.parse_sess, Box::new(srdr));
92+
p.parse_all_token_trees().expect("Couldn't re-parse span")
93+
}
94+
9095
// Re-parses a path and returns the span for the last identifier in the path
9196
pub fn span_for_last_ident(&self, span: Span) -> Option<Span> {
9297
let mut result = None;
@@ -308,6 +313,42 @@ impl<'a> SpanUtils<'a> {
308313
}
309314
}
310315

316+
/// `span` must be the span for an item such as a function or struct. This
317+
/// function returns the program text from the start of the span until the
318+
/// end of the 'signature' part, that is up to, but not including an opening
319+
/// brace or semicolon.
320+
pub fn signature_string_for_span(&self, span: Span) -> Option<String> {
321+
let mut toks = self.span_to_tts(span).into_iter();
322+
let mut prev = toks.next().unwrap();
323+
let first_span = prev.get_span();
324+
let mut angle_count = 0;
325+
for tok in toks {
326+
if let TokenTree::Token(_, ref tok) = prev {
327+
angle_count += match *tok {
328+
token::Eof => { return None; }
329+
token::Lt => 1,
330+
token::Gt => -1,
331+
token::BinOp(token::Shl) => 2,
332+
token::BinOp(token::Shr) => -2,
333+
_ => 0,
334+
};
335+
}
336+
if angle_count > 0 {
337+
prev = tok;
338+
continue;
339+
}
340+
if let TokenTree::Token(_, token::Semi) = tok {
341+
return Some(self.snippet(mk_sp(first_span.lo, prev.get_span().hi)));
342+
} else if let TokenTree::Delimited(_, ref d) = tok {
343+
if d.delim == token::Brace {
344+
return Some(self.snippet(mk_sp(first_span.lo, prev.get_span().hi)));
345+
}
346+
}
347+
prev = tok;
348+
}
349+
None
350+
}
351+
311352
pub fn sub_span_before_token(&self, span: Span, tok: Token) -> Option<Span> {
312353
let mut toks = self.retokenise_span(span);
313354
let mut prev = toks.real_token();

0 commit comments

Comments
 (0)