Auto merge of #38529 - nrc:save-sig, r=nikomatsakis

save-analysis: add signature info

These 'signatures' for definitions contain enough info for the RLS to create Rustdoc-style info on the fly.
This commit is contained in:
bors 2016-12-23 15:59:07 +00:00
commit 00b4019f28
7 changed files with 320 additions and 16 deletions

View file

@ -135,6 +135,7 @@ pub struct EnumData {
pub variants: Vec<NodeId>,
pub visibility: Visibility,
pub docs: String,
pub sig: Signature,
}
/// Data for extern crates.
@ -169,6 +170,7 @@ pub struct FunctionData {
pub visibility: Visibility,
pub parent: Option<DefId>,
pub docs: String,
pub sig: Signature,
}
/// Data about a function call.
@ -253,6 +255,7 @@ pub struct MethodData {
pub parent: Option<DefId>,
pub visibility: Visibility,
pub docs: String,
pub sig: Signature,
}
/// Data for modules.
@ -267,6 +270,7 @@ pub struct ModData {
pub items: Vec<NodeId>,
pub visibility: Visibility,
pub docs: String,
pub sig: Signature,
}
/// Data for a reference to a module.
@ -290,6 +294,7 @@ pub struct StructData {
pub fields: Vec<NodeId>,
pub visibility: Visibility,
pub docs: String,
pub sig: Signature,
}
#[derive(Debug, RustcEncodable)]
@ -303,6 +308,7 @@ pub struct StructVariantData {
pub scope: NodeId,
pub parent: Option<DefId>,
pub docs: String,
pub sig: Signature,
}
#[derive(Debug, RustcEncodable)]
@ -316,6 +322,7 @@ pub struct TraitData {
pub items: Vec<NodeId>,
pub visibility: Visibility,
pub docs: String,
pub sig: Signature,
}
#[derive(Debug, RustcEncodable)]
@ -329,6 +336,7 @@ pub struct TupleVariantData {
pub scope: NodeId,
pub parent: Option<DefId>,
pub docs: String,
pub sig: Signature,
}
/// Data for a typedef.
@ -342,6 +350,7 @@ pub struct TypeDefData {
pub visibility: Visibility,
pub parent: Option<DefId>,
pub docs: String,
pub sig: Option<Signature>,
}
/// Data for a reference to a type or trait.
@ -386,6 +395,7 @@ pub struct VariableData {
pub type_value: String,
pub visibility: Visibility,
pub docs: String,
pub sig: Option<Signature>,
}
#[derive(Debug, RustcEncodable)]
@ -405,3 +415,28 @@ pub struct VariableRefData {
pub scope: NodeId,
pub ref_id: DefId,
}
/// Encodes information about the signature of a definition. This should have
/// enough information to create a nice display about a definition without
/// access to the source code.
#[derive(Clone, Debug, RustcEncodable)]
pub struct Signature {
pub span: Span,
pub text: String,
// These identify the main identifier for the defintion as byte offsets into
// `text`. E.g., of `foo` in `pub fn foo(...)`
pub ident_start: usize,
pub ident_end: usize,
pub defs: Vec<SigElement>,
pub refs: Vec<SigElement>,
}
/// An element of a signature. `start` and `end` are byte offsets into the `text`
/// of the parent `Signature`.
#[derive(Clone, Debug, RustcEncodable)]
pub struct SigElement {
pub id: DefId,
pub start: usize,
pub end: usize,
}

View file

@ -357,6 +357,7 @@ fn process_formals(&mut self, formals: &'l [ast::Arg], qualname: &str) {
parent: None,
visibility: Visibility::Inherited,
docs: String::new(),
sig: None,
}.lower(self.tcx));
}
}
@ -429,6 +430,7 @@ fn process_method(&mut self,
parent: trait_id,
visibility: vis,
docs: docs_for_attrs(attrs),
sig: method_data.sig,
}.lower(self.tcx));
}
@ -500,6 +502,7 @@ fn process_generic_params(&mut self,
visibility: Visibility::Inherited,
parent: None,
docs: String::new(),
sig: None,
}.lower(self.tcx));
}
}
@ -572,6 +575,7 @@ fn process_assoc_const(&mut self,
parent: Some(parent_id),
visibility: vis,
docs: docs_for_attrs(attrs),
sig: None,
}.lower(self.tcx));
}
@ -615,11 +619,10 @@ fn process_struct(&mut self,
fields: fields,
visibility: From::from(&item.vis),
docs: docs_for_attrs(&item.attrs),
sig: self.save_ctxt.sig_base(item),
}.lower(self.tcx));
}
// fields
for field in def.fields() {
self.process_struct_field_def(field, item.id);
self.visit_ty(&field.ty);
@ -648,6 +651,18 @@ fn process_enum(&mut self,
qualname.push_str("::");
qualname.push_str(&name);
let text = self.span.signature_string_for_span(variant.span);
let ident_start = text.find(&name).unwrap();
let ident_end = ident_start + name.len();
let sig = Signature {
span: variant.span,
text: text,
ident_start: ident_start,
ident_end: ident_end,
defs: vec![],
refs: vec![],
};
match variant.node.data {
ast::VariantData::Struct(ref fields, _) => {
let sub_span = self.span.span_for_first_ident(variant.span);
@ -669,6 +684,7 @@ fn process_enum(&mut self,
scope: enum_data.scope,
parent: Some(make_def_id(item.id, &self.tcx.map)),
docs: docs_for_attrs(&variant.node.attrs),
sig: sig,
}.lower(self.tcx));
}
}
@ -694,6 +710,7 @@ fn process_enum(&mut self,
scope: enum_data.scope,
parent: Some(make_def_id(item.id, &self.tcx.map)),
docs: docs_for_attrs(&variant.node.attrs),
sig: sig,
}.lower(self.tcx));
}
}
@ -778,6 +795,7 @@ fn process_trait(&mut self,
items: methods.iter().map(|i| i.id).collect(),
visibility: From::from(&item.vis),
docs: docs_for_attrs(&item.attrs),
sig: self.save_ctxt.sig_base(item),
}.lower(self.tcx));
}
@ -1043,6 +1061,7 @@ fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) {
parent: None,
visibility: Visibility::Inherited,
docs: String::new(),
sig: None,
}.lower(self.tcx));
}
}
@ -1257,10 +1276,10 @@ fn visit_item(&mut self, item: &'l ast::Item) {
Struct(ref def, ref ty_params) => self.process_struct(item, def, ty_params),
Enum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
Impl(..,
ref ty_params,
ref trait_ref,
ref typ,
ref impl_items) => {
ref ty_params,
ref trait_ref,
ref typ,
ref impl_items) => {
self.process_impl(item, ty_params, trait_ref, &typ, impl_items)
}
Trait(_, ref generics, ref trait_refs, ref methods) =>
@ -1283,6 +1302,7 @@ fn visit_item(&mut self, item: &'l ast::Item) {
visibility: From::from(&item.vis),
parent: None,
docs: docs_for_attrs(&item.attrs),
sig: Some(self.save_ctxt.sig_base(item)),
}.lower(self.tcx));
}
@ -1492,6 +1512,7 @@ fn visit_arm(&mut self, arm: &'l ast::Arm) {
parent: None,
visibility: Visibility::Inherited,
docs: String::new(),
sig: None,
}.lower(self.tcx));
}
}

View file

@ -15,7 +15,7 @@
use syntax::codemap::CodeMap;
use syntax_pos::Span;
use data::{self, Visibility};
use data::{self, Visibility, SigElement};
// FIXME: this should be pub(crate), but the current snapshot doesn't allow it yet
pub trait Lower {
@ -97,6 +97,7 @@ pub struct EnumData {
pub variants: Vec<DefId>,
pub visibility: Visibility,
pub docs: String,
pub sig: Signature,
}
impl Lower for data::EnumData {
@ -113,6 +114,7 @@ fn lower(self, tcx: TyCtxt) -> EnumData {
variants: self.variants.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(),
visibility: self.visibility,
docs: self.docs,
sig: self.sig.lower(tcx),
}
}
}
@ -176,6 +178,7 @@ pub struct FunctionData {
pub visibility: Visibility,
pub parent: Option<DefId>,
pub docs: String,
pub sig: Signature,
}
impl Lower for data::FunctionData {
@ -193,6 +196,7 @@ fn lower(self, tcx: TyCtxt) -> FunctionData {
visibility: self.visibility,
parent: self.parent,
docs: self.docs,
sig: self.sig.lower(tcx),
}
}
}
@ -341,6 +345,7 @@ pub struct MethodData {
pub visibility: Visibility,
pub parent: Option<DefId>,
pub docs: String,
pub sig: Signature,
}
impl Lower for data::MethodData {
@ -358,6 +363,7 @@ fn lower(self, tcx: TyCtxt) -> MethodData {
visibility: self.visibility,
parent: self.parent,
docs: self.docs,
sig: self.sig.lower(tcx),
}
}
}
@ -374,6 +380,7 @@ pub struct ModData {
pub items: Vec<DefId>,
pub visibility: Visibility,
pub docs: String,
pub sig: Signature,
}
impl Lower for data::ModData {
@ -390,6 +397,7 @@ fn lower(self, tcx: TyCtxt) -> ModData {
items: self.items.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(),
visibility: self.visibility,
docs: self.docs,
sig: self.sig.lower(tcx),
}
}
}
@ -428,6 +436,7 @@ pub struct StructData {
pub fields: Vec<DefId>,
pub visibility: Visibility,
pub docs: String,
pub sig: Signature,
}
impl Lower for data::StructData {
@ -445,6 +454,7 @@ fn lower(self, tcx: TyCtxt) -> StructData {
fields: self.fields.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(),
visibility: self.visibility,
docs: self.docs,
sig: self.sig.lower(tcx),
}
}
}
@ -460,6 +470,7 @@ pub struct StructVariantData {
pub scope: DefId,
pub parent: Option<DefId>,
pub docs: String,
pub sig: Signature,
}
impl Lower for data::StructVariantData {
@ -476,6 +487,7 @@ fn lower(self, tcx: TyCtxt) -> StructVariantData {
scope: make_def_id(self.scope, &tcx.map),
parent: self.parent,
docs: self.docs,
sig: self.sig.lower(tcx),
}
}
}
@ -491,6 +503,7 @@ pub struct TraitData {
pub items: Vec<DefId>,
pub visibility: Visibility,
pub docs: String,
pub sig: Signature,
}
impl Lower for data::TraitData {
@ -507,6 +520,7 @@ fn lower(self, tcx: TyCtxt) -> TraitData {
items: self.items.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(),
visibility: self.visibility,
docs: self.docs,
sig: self.sig.lower(tcx),
}
}
}
@ -522,6 +536,7 @@ pub struct TupleVariantData {
pub scope: DefId,
pub parent: Option<DefId>,
pub docs: String,
pub sig: Signature,
}
impl Lower for data::TupleVariantData {
@ -538,6 +553,7 @@ fn lower(self, tcx: TyCtxt) -> TupleVariantData {
scope: make_def_id(self.scope, &tcx.map),
parent: self.parent,
docs: self.docs,
sig: self.sig.lower(tcx),
}
}
}
@ -553,6 +569,7 @@ pub struct TypeDefData {
pub visibility: Visibility,
pub parent: Option<DefId>,
pub docs: String,
pub sig: Option<Signature>,
}
impl Lower for data::TypeDefData {
@ -568,6 +585,7 @@ fn lower(self, tcx: TyCtxt) -> TypeDefData {
visibility: self.visibility,
parent: self.parent,
docs: self.docs,
sig: self.sig.map(|s| s.lower(tcx)),
}
}
}
@ -656,6 +674,7 @@ pub struct VariableData {
pub parent: Option<DefId>,
pub visibility: Visibility,
pub docs: String,
pub sig: Option<Signature>,
}
impl Lower for data::VariableData {
@ -674,6 +693,7 @@ fn lower(self, tcx: TyCtxt) -> VariableData {
parent: self.parent,
visibility: self.visibility,
docs: self.docs,
sig: self.sig.map(|s| s.lower(tcx)),
}
}
}
@ -700,3 +720,30 @@ fn lower(self, tcx: TyCtxt) -> VariableRefData {
}
}
}
#[derive(Clone, Debug, RustcEncodable)]
pub struct Signature {
pub span: SpanData,
pub text: String,
// These identify the main identifier for the defintion as byte offsets into
// `text`. E.g., of `foo` in `pub fn foo(...)`
pub ident_start: usize,
pub ident_end: usize,
pub defs: Vec<SigElement>,
pub refs: Vec<SigElement>,
}
impl Lower for data::Signature {
type Target = Signature;
fn lower(self, tcx: TyCtxt) -> Signature {
Signature {
span: SpanData::from_span(self.span, tcx.sess.codemap()),
text: self.text,
ident_start: self.ident_start,
ident_end: self.ident_end,
defs: self.defs,
refs: self.refs,
}
}
}

View file

@ -14,7 +14,7 @@
use rustc_serialize::json::as_json;
use external_data::*;
use data::{VariableKind, Visibility};
use data::{VariableKind, Visibility, SigElement};
use dump::Dump;
use super::Format;
@ -179,6 +179,7 @@ struct Def {
children: Vec<Id>,
decl_id: Option<Id>,
docs: String,
sig: Option<JsonSignature>,
}
#[derive(Debug, RustcEncodable)]
@ -221,6 +222,7 @@ fn from(data: EnumData) -> Option<Def> {
children: data.variants.into_iter().map(|id| From::from(id)).collect(),
decl_id: None,
docs: data.docs,
sig: Some(From::from(data.sig)),
}),
_ => None,
}
@ -240,6 +242,7 @@ fn from(data: TupleVariantData) -> Option<Def> {
children: vec![],
decl_id: None,
docs: data.docs,
sig: Some(From::from(data.sig)),
})
}
}
@ -256,6 +259,7 @@ fn from(data: StructVariantData) -> Option<Def> {
children: vec![],
decl_id: None,
docs: data.docs,
sig: Some(From::from(data.sig)),
})
}
}
@ -273,6 +277,7 @@ fn from(data: StructData) -> Option<Def> {
children: data.fields.into_iter().map(|id| From::from(id)).collect(),
decl_id: None,
docs: data.docs,
sig: Some(From::from(data.sig)),
}),
_ => None,
}
@ -292,6 +297,7 @@ fn from(data: TraitData) -> Option<Def> {
parent: None,
decl_id: None,
docs: data.docs,
sig: Some(From::from(data.sig)),
}),
_ => None,
}
@ -311,6 +317,7 @@ fn from(data: FunctionData) -> Option<Def> {
parent: data.parent.map(|id| From::from(id)),
decl_id: None,
docs: data.docs,
sig: Some(From::from(data.sig)),
}),
_ => None,
}
@ -330,6 +337,7 @@ fn from(data: MethodData) -> Option<Def> {
parent: data.parent.map(|id| From::from(id)),
decl_id: data.decl_id.map(|id| From::from(id)),
docs: data.docs,
sig: Some(From::from(data.sig)),
}),
_ => None,
}
@ -348,6 +356,7 @@ fn from(data: MacroData) -> Option<Def> {
parent: None,
decl_id: None,
docs: data.docs,
sig: None,
})
}
}
@ -365,6 +374,7 @@ fn from(data:ModData) -> Option<Def> {
parent: None,
decl_id: None,
docs: data.docs,
sig: Some(From::from(data.sig)),
}),
_ => None,
}
@ -384,11 +394,13 @@ fn from(data: TypeDefData) -> Option<Def> {
parent: data.parent.map(|id| From::from(id)),
decl_id: None,
docs: String::new(),
sig: data.sig.map(|s| From::from(s)),
}),
_ => None,
}
}
}
impl From<VariableData> for Option<Def> {
fn from(data: VariableData) -> Option<Def> {
match data.visibility {
@ -408,8 +420,49 @@ fn from(data: VariableData) -> Option<Def> {
parent: data.parent.map(|id| From::from(id)),
decl_id: None,
docs: data.docs,
sig: data.sig.map(|s| From::from(s)),
}),
_ => None,
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct JsonSignature {
span: SpanData,
text: String,
ident_start: usize,
ident_end: usize,
defs: Vec<JsonSigElement>,
refs: Vec<JsonSigElement>,
}
impl From<Signature> for JsonSignature {
fn from(data: Signature) -> JsonSignature {
JsonSignature {
span: data.span,
text: data.text,
ident_start: data.ident_start,
ident_end: data.ident_end,
defs: data.defs.into_iter().map(|s| From::from(s)).collect(),
refs: data.refs.into_iter().map(|s| From::from(s)).collect(),
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct JsonSigElement {
id: Id,
start: usize,
end: usize,
}
impl From<SigElement> for JsonSigElement {
fn from(data: SigElement) -> JsonSigElement {
JsonSigElement {
id: From::from(data.id),
start: data.start,
end: data.end,
}
}
}

View file

@ -14,7 +14,7 @@
use rustc_serialize::json::as_json;
use external_data::*;
use data::VariableKind;
use data::{VariableKind, SigElement};
use dump::Dump;
use super::Format;
@ -86,6 +86,7 @@ fn mod_data(&mut self, data: ModData) {
children: data.items.into_iter().map(|id| From::from(id)).collect(),
decl_id: None,
docs: data.docs,
sig: Some(From::from(data.sig)),
};
if def.span.file_name != def.value {
// If the module is an out-of-line defintion, then we'll make the
@ -223,6 +224,7 @@ struct Def {
children: Vec<Id>,
decl_id: Option<Id>,
docs: String,
sig: Option<JsonSignature>,
}
#[derive(Debug, RustcEncodable)]
@ -264,6 +266,7 @@ fn from(data: EnumData) -> Def {
children: data.variants.into_iter().map(|id| From::from(id)).collect(),
decl_id: None,
docs: data.docs,
sig: Some(From::from(data.sig)),
}
}
}
@ -280,6 +283,7 @@ fn from(data: TupleVariantData) -> Def {
children: vec![],
decl_id: None,
docs: data.docs,
sig: Some(From::from(data.sig)),
}
}
}
@ -295,6 +299,7 @@ fn from(data: StructVariantData) -> Def {
children: vec![],
decl_id: None,
docs: data.docs,
sig: Some(From::from(data.sig)),
}
}
}
@ -310,6 +315,7 @@ fn from(data: StructData) -> Def {
children: data.fields.into_iter().map(|id| From::from(id)).collect(),
decl_id: None,
docs: data.docs,
sig: Some(From::from(data.sig)),
}
}
}
@ -325,6 +331,7 @@ fn from(data: TraitData) -> Def {
children: data.items.into_iter().map(|id| From::from(id)).collect(),
decl_id: None,
docs: data.docs,
sig: Some(From::from(data.sig)),
}
}
}
@ -340,6 +347,7 @@ fn from(data: FunctionData) -> Def {
children: vec![],
decl_id: None,
docs: data.docs,
sig: Some(From::from(data.sig)),
}
}
}
@ -355,6 +363,7 @@ fn from(data: MethodData) -> Def {
children: vec![],
decl_id: data.decl_id.map(|id| From::from(id)),
docs: data.docs,
sig: Some(From::from(data.sig)),
}
}
}
@ -370,10 +379,10 @@ fn from(data: MacroData) -> Def {
children: vec![],
decl_id: None,
docs: data.docs,
sig: None,
}
}
}
impl From<TypeDefData> for Def {
fn from(data: TypeDefData) -> Def {
Def {
@ -386,6 +395,7 @@ fn from(data: TypeDefData) -> Def {
children: vec![],
decl_id: None,
docs: String::new(),
sig: data.sig.map(|s| From::from(s)),
}
}
}
@ -406,6 +416,7 @@ fn from(data: VariableData) -> Def {
children: vec![],
decl_id: None,
docs: data.docs,
sig: None,
}
}
}
@ -496,3 +507,43 @@ fn from(data: MacroUseData) -> MacroRef {
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct JsonSignature {
span: SpanData,
text: String,
ident_start: usize,
ident_end: usize,
defs: Vec<JsonSigElement>,
refs: Vec<JsonSigElement>,
}
impl From<Signature> for JsonSignature {
fn from(data: Signature) -> JsonSignature {
JsonSignature {
span: data.span,
text: data.text,
ident_start: data.ident_start,
ident_end: data.ident_end,
defs: data.defs.into_iter().map(|s| From::from(s)).collect(),
refs: data.refs.into_iter().map(|s| From::from(s)).collect(),
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct JsonSigElement {
id: Id,
start: usize,
end: usize,
}
impl From<SigElement> for JsonSigElement {
fn from(data: SigElement) -> JsonSigElement {
JsonSigElement {
id: From::from(data.id),
start: data.start,
end: data.end,
}
}
}

View file

@ -152,6 +152,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
visibility: From::from(&item.vis),
parent: None,
docs: docs_for_attrs(&item.attrs),
sig: self.sig_base(item),
}))
}
ast::ItemKind::Static(ref typ, mt, ref expr) => {
@ -179,6 +180,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
type_value: ty_to_string(&typ),
visibility: From::from(&item.vis),
docs: docs_for_attrs(&item.attrs),
sig: Some(self.sig_base(item)),
}))
}
ast::ItemKind::Const(ref typ, ref expr) => {
@ -197,6 +199,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
type_value: ty_to_string(&typ),
visibility: From::from(&item.vis),
docs: docs_for_attrs(&item.attrs),
sig: Some(self.sig_base(item)),
}))
}
ast::ItemKind::Mod(ref m) => {
@ -207,6 +210,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Mod);
filter!(self.span_utils, sub_span, item.span, None);
Some(Data::ModData(ModData {
id: item.id,
name: item.ident.to_string(),
@ -217,6 +221,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
items: m.items.iter().map(|i| i.id).collect(),
visibility: From::from(&item.vis),
docs: docs_for_attrs(&item.attrs),
sig: self.sig_base(item),
}))
}
ast::ItemKind::Enum(ref def, _) => {
@ -239,6 +244,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
variants: def.variants.iter().map(|v| v.node.data.id()).collect(),
visibility: From::from(&item.vis),
docs: docs_for_attrs(&item.attrs),
sig: self.sig_base(item),
}))
}
ast::ItemKind::Impl(.., ref trait_ref, ref typ, _) => {
@ -287,18 +293,34 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
}
}
pub fn get_field_data(&self, field: &ast::StructField,
scope: NodeId) -> Option<VariableData> {
pub fn get_field_data(&self,
field: &ast::StructField,
scope: NodeId)
-> Option<VariableData> {
if let Some(ident) = field.ident {
let name = ident.to_string();
let qualname = format!("::{}::{}", self.tcx.node_path_str(scope), ident);
let def_id = self.tcx.map.local_def_id(field.id);
let typ = self.tcx.item_type(def_id).to_string();
let sub_span = self.span_utils.sub_span_before_token(field.span, token::Colon);
filter!(self.span_utils, sub_span, field.span, None);
let def_id = self.tcx.map.local_def_id(field.id);
let typ = self.tcx.item_type(def_id).to_string();
let span = field.span;
let text = self.span_utils.snippet(field.span);
let ident_start = text.find(&name).unwrap();
let ident_end = ident_start + name.len();
let sig = Signature {
span: span,
text: text,
ident_start: ident_start,
ident_end: ident_end,
defs: vec![],
refs: vec![],
};
Some(VariableData {
id: field.id,
kind: VariableKind::Field,
name: ident.to_string(),
name: name,
qualname: qualname,
span: sub_span.unwrap(),
scope: scope,
@ -307,6 +329,7 @@ pub fn get_field_data(&self, field: &ast::StructField,
type_value: typ,
visibility: From::from(&field.vis),
docs: docs_for_attrs(&field.attrs),
sig: Some(sig),
})
} else {
None
@ -388,9 +411,23 @@ pub fn get_method_data(&self, id: ast::NodeId,
let sub_span = self.span_utils.sub_span_after_keyword(span, keywords::Fn);
filter!(self.span_utils, sub_span, span, None);
let name = name.to_string();
let text = self.span_utils.signature_string_for_span(span);
let ident_start = text.find(&name).unwrap();
let ident_end = ident_start + name.len();
let sig = Signature {
span: span,
text: text,
ident_start: ident_start,
ident_end: ident_end,
defs: vec![],
refs: vec![],
};
Some(FunctionData {
id: id,
name: name.to_string(),
name: name,
qualname: qualname,
declaration: decl_id,
span: sub_span.unwrap(),
@ -400,6 +437,7 @@ pub fn get_method_data(&self, id: ast::NodeId,
visibility: vis,
parent: parent_scope,
docs: docs,
sig: sig,
})
}
@ -695,6 +733,21 @@ fn lookup_ref_id(&self, ref_id: NodeId) -> Option<DefId> {
}
}
fn sig_base(&self, item: &ast::Item) -> 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.map.get_enclosing_scope(id).unwrap_or(CRATE_NODE_ID)

View file

@ -19,7 +19,9 @@
use syntax::ast;
use syntax::parse::lexer::{self, Reader, StringReader};
use syntax::parse::token::{self, Token};
use syntax::parse::parser::Parser;
use syntax::symbol::keywords;
use syntax::tokenstream::TokenTree;
use syntax_pos::*;
#[derive(Clone)]
@ -87,6 +89,12 @@ pub fn retokenise_span(&self, span: Span) -> StringReader<'a> {
lexer::StringReader::new(s.diagnostic(), filemap)
}
fn span_to_tts(&self, span: Span) -> Vec<TokenTree> {
let srdr = self.retokenise_span(span);
let mut p = Parser::new(&self.sess.parse_sess, Box::new(srdr), None, false);
p.parse_all_token_trees().expect("Couldn't re-parse span")
}
// Re-parses a path and returns the span for the last identifier in the path
pub fn span_for_last_ident(&self, span: Span) -> Option<Span> {
let mut result = None;
@ -308,6 +316,42 @@ pub fn spans_with_brackets(&self, span: Span, nesting: isize, limit: isize) -> V
}
}
/// `span` must be the span for an item such as a function or struct. This
/// function returns the program text from the start of the span until the
/// end of the 'signature' part, that is up to, but not including an opening
/// brace or semicolon.
pub fn signature_string_for_span(&self, span: Span) -> String {
let mut toks = self.span_to_tts(span).into_iter();
let mut prev = toks.next().unwrap();
let first_span = prev.get_span();
let mut angle_count = 0;
for tok in toks {
if let TokenTree::Token(_, ref tok) = prev {
angle_count += match *tok {
token::Eof => { break; }
token::Lt => 1,
token::Gt => -1,
token::BinOp(token::Shl) => 2,
token::BinOp(token::Shr) => -2,
_ => 0,
};
}
if angle_count > 0 {
prev = tok;
continue;
}
if let TokenTree::Token(_, token::Semi) = tok {
return self.snippet(mk_sp(first_span.lo, prev.get_span().hi));
} else if let TokenTree::Delimited(_, ref d) = tok {
if d.delim == token::Brace {
return self.snippet(mk_sp(first_span.lo, prev.get_span().hi));
}
}
prev = tok;
}
self.snippet(span)
}
pub fn sub_span_before_token(&self, span: Span, tok: Token) -> Option<Span> {
let mut toks = self.retokenise_span(span);
let mut prev = toks.real_token();