From 600237fa1962027e281383709691475d44e048aa Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 30 May 2017 10:37:11 +1200 Subject: [PATCH 1/9] Add a sig module to save-analysis Generates signatures for use in Rustdoc and similar tools. --- src/librustc_save_analysis/lib.rs | 1 + src/librustc_save_analysis/sig.rs | 560 ++++++++++++++++++++++++++++++ src/libsyntax/print/pprust.rs | 27 +- 3 files changed, 581 insertions(+), 7 deletions(-) create mode 100644 src/librustc_save_analysis/sig.rs diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index b74d3982d61c5..655901aa8591c 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -44,6 +44,7 @@ mod dump_visitor; pub mod external_data; #[macro_use] pub mod span_utils; +mod sig; use rustc::hir; use rustc::hir::def::Def; diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs new file mode 100644 index 0000000000000..945f405659d53 --- /dev/null +++ b/src/librustc_save_analysis/sig.rs @@ -0,0 +1,560 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// FIXME? None of these include visibility info. +// Large outstanding things - where clauses, defs/refs for generics +// paresable - each sig ends with `;` of ` {}` + +use SaveContext; + +use rls_data::{Signature, SigElement, Id}; + +use rustc::hir::def::Def; +use rustc::hir::def_id::DefId; +use syntax::ast::{self, NodeId}; +use syntax::print::pprust; + + +// TODO dup from json_dumper +fn id_from_def_id(id: DefId) -> Id { + Id { + krate: id.krate.as_u32(), + index: id.index.as_u32(), + } +} + +fn id_from_node_id(id: NodeId, scx: &SaveContext) -> Id { + let def_id = scx.tcx.hir.local_def_id(id); + id_from_def_id(def_id) +} + +type Result = ::std::result::Result; + +trait Sig { + fn make(&self, offset: usize, id: Option, scx: &SaveContext) -> Result; +} + +fn extend_sig(mut sig: Signature, + text: String, + defs: Vec, + refs: Vec) + -> Signature { + sig.text = text; + sig.defs.extend(defs.into_iter()); + sig.refs.extend(refs.into_iter()); + sig +} + +fn replace_text(mut sig: Signature, text: String) -> Signature { + sig.text = text; + sig +} + +fn merge_sigs(text: String, sigs: Vec) -> Signature { + let mut result = Signature { + text, + defs: vec![], + refs: vec![], + }; + + let (defs, refs): (Vec<_>, Vec<_>) = sigs.into_iter().map(|s| (s.defs, s.refs)).unzip(); + + result.defs.extend(defs.into_iter().flat_map(|ds| ds.into_iter())); + result.refs.extend(refs.into_iter().flat_map(|rs| rs.into_iter())); + + result +} + +fn text_sig(text: String) -> Signature { + Signature { + text: text, + defs: vec![], + refs: vec![], + } +} + +impl Sig for ast::Ty { + fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { + let id = Some(self.id); + match self.node { + ast::TyKind::Slice(ref ty) => { + let nested = ty.make(offset + 1, id, scx)?; + let text = format!("[{}]", nested.text); + Ok(replace_text(nested, text)) + } + ast::TyKind::Ptr(ref mt) => { + let prefix = match mt.mutbl { + ast::Mutability::Mutable => "*mut ", + ast::Mutability::Immutable => "*const ", + }; + let nested = mt.ty.make(offset + prefix.len(), id, scx)?; + let text = format!("{}{}", prefix, nested.text); + Ok(replace_text(nested, text)) + } + ast::TyKind::Rptr(ref lifetime, ref mt) => { + let mut prefix = "&".to_owned(); + if let &Some(ref l) = lifetime { + prefix.push_str(&l.ident.to_string()); + prefix.push(' '); + } + if let ast::Mutability::Mutable = mt.mutbl { + prefix.push_str("mut "); + }; + + let nested = mt.ty.make(offset + prefix.len(), id, scx)?; + let text = format!("{}{}", prefix, nested.text); + Ok(replace_text(nested, text)) + } + ast::TyKind::Never => { + Ok(text_sig("!".to_owned())) + }, + ast::TyKind::Tup(ref ts) => { + let mut text = "(".to_owned(); + let mut defs = vec![]; + let mut refs = vec![]; + for t in ts { + let nested = t.make(offset + text.len(), id, scx)?; + text.push_str(&nested.text); + text.push(','); + defs.extend(nested.defs.into_iter()); + refs.extend(nested.refs.into_iter()); + } + text.push(')'); + Ok(Signature { text, defs, refs }) + } + ast::TyKind::Paren(ref ty) => { + let nested = ty.make(offset + 1, id, scx)?; + let text = format!("({})", nested.text); + Ok(replace_text(nested, text)) + } + ast::TyKind::BareFn(ref f) => { + let mut text = String::new(); + if !f.lifetimes.is_empty() { + // FIXME defs, bounds on lifetimes + text.push_str("for<"); + text.push_str(&f.lifetimes.iter().map(|l| + l.lifetime.ident.to_string()).collect::>().join(", ")); + text.push('>'); + } + + if f.unsafety == ast::Unsafety::Unsafe { + text.push_str("unsafe "); + } + if f.abi != ::syntax::abi::Abi::Rust { + text.push_str("extern"); + text.push_str(&f.abi.to_string()); + text.push(' '); + } + text.push_str("fn("); + + let mut defs = vec![]; + let mut refs = vec![]; + for i in &f.decl.inputs { + let nested = i.ty.make(offset + text.len(), Some(i.id), scx)?; + text.push_str(&nested.text); + text.push(','); + defs.extend(nested.defs.into_iter()); + refs.extend(nested.refs.into_iter()); + } + text.push(')'); + if let ast::FunctionRetTy::Ty(ref t) = f.decl.output { + text.push_str(" -> "); + let nested = t.make(offset + text.len(), None, scx)?; + text.push_str(&nested.text); + text.push(','); + defs.extend(nested.defs.into_iter()); + refs.extend(nested.refs.into_iter()); + } + + Ok(Signature { text, defs, refs }) + } + ast::TyKind::Path(None, ref path) => { + path.make(offset, id, scx) + } + ast::TyKind::Path(Some(ref qself), ref path) => { + let nested_ty = qself.ty.make(offset + 1, id, scx)?; + let prefix = if qself.position == 0 { + format!("<{}>::", nested_ty.text) + } else if qself.position == 1 { + let first = pprust::path_segment_to_string(&path.segments[0]); + format!("<{} as {}>::", nested_ty.text, first) + } else { + // FIXME handle path instead of elipses. + format!("<{} as ...>::", nested_ty.text) + }; + + let name = pprust::path_segment_to_string(path.segments.last().ok_or("Bad path")?); + let def = scx.get_path_def(id.ok_or("Missing id for Path")?); + let id = id_from_def_id(def.def_id()); + if path.segments.len() - qself.position == 1 { + let start = offset + prefix.len(); + let end = start + name.len(); + + Ok(Signature { + text: prefix + &name, + defs: vec![], + refs: vec![SigElement { id, start, end }], + }) + } else { + let start = offset + prefix.len() + 5; + let end = start + name.len(); + // FIXME should put the proper path in there, not elipses. + Ok(Signature { + text: prefix + "...::" + &name, + defs: vec![], + refs: vec![SigElement { id, start, end }], + }) + } + } + ast::TyKind::TraitObject(ref bounds) => { + // FIXME recurse into bounds + let nested = pprust::bounds_to_string(bounds); + Ok(text_sig(nested)) + } + ast::TyKind::ImplTrait(ref bounds) => { + // FIXME recurse into bounds + let nested = pprust::bounds_to_string(bounds); + Ok(text_sig(format!("impl {}", nested))) + } + ast::TyKind::Array(ref ty, ref v) => { + let nested_ty = ty.make(offset + 1, id, scx)?; + let expr = pprust::expr_to_string(v).replace('\n', " "); + let text = format!("[{}; {}]", nested_ty.text, expr); + Ok(replace_text(nested_ty, text)) + } + ast::TyKind::Typeof(_) | + ast::TyKind::Infer | + ast::TyKind::Err | + ast::TyKind::ImplicitSelf | + ast::TyKind::Mac(_) => Err("Ty"), + } + } +} + +impl Sig for ast::Item { + fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { + let id = Some(self.id); + + let name_and_generics = |mut text: String, generics: &ast::Generics| -> Result { + let name = self.ident.to_string(); + let def = SigElement { + id: id_from_node_id(self.id, scx), + start: offset + 5, + end: offset + 5 + name.len(), + }; + text.push_str(&name); + let generics: Signature = generics.make(offset + text.len(), id, scx)?; + // FIXME where clause + let text = format!("{}{}", text, generics.text); + Ok(extend_sig(generics, text, vec![def], vec![])) + }; + + match self.node { + ast::ItemKind::Static(ref ty, m, ref expr) => { + let mut text = "static ".to_owned(); + if m == ast::Mutability::Mutable { + text.push_str("mut "); + } + let name = self.ident.to_string(); + let defs = vec![SigElement { + id: id_from_node_id(self.id, scx), + start: offset + text.len(), + end: offset + text.len() + name.len(), + }]; + text.push_str(&name); + text.push_str(": "); + + let ty = ty.make(offset + text.len(), id, scx)?; + text.push_str(&ty.text); + text.push_str(" = "); + + let expr = pprust::expr_to_string(expr).replace('\n', " "); + text.push_str(&expr); + text.push(';'); + + Ok(extend_sig(ty, text, defs, vec![])) + } + ast::ItemKind::Const(ref ty, ref expr) => { + let mut text = "const ".to_owned(); + let name = self.ident.to_string(); + let defs = vec![SigElement { + id: id_from_node_id(self.id, scx), + start: offset + text.len(), + end: offset + text.len() + name.len(), + }]; + text.push_str(&name); + text.push_str(": "); + + let ty = ty.make(offset + text.len(), id, scx)?; + text.push_str(&ty.text); + text.push_str(" = "); + + let expr = pprust::expr_to_string(expr).replace('\n', " "); + text.push_str(&expr); + text.push(';'); + + Ok(extend_sig(ty, text, defs, vec![])) + } + ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, _) => { + let mut text = String::new(); + if constness.node == ast::Constness::Const { + text.push_str("const "); + } + if unsafety == ast::Unsafety::Unsafe { + text.push_str("unsafe "); + } + if abi != ::syntax::abi::Abi::Rust { + text.push_str("extern"); + text.push_str(&abi.to_string()); + text.push(' '); + } + text.push_str("fn "); + + let mut sig = name_and_generics(text, generics)?; + + sig.text.push('('); + for i in &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(offset + 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) = decl.output { + sig.text.push_str(" -> "); + let nested = t.make(offset + sig.text.len(), None, scx)?; + sig.text.push_str(&nested.text); + sig.text.push(','); + sig.defs.extend(nested.defs.into_iter()); + sig.refs.extend(nested.refs.into_iter()); + } + + Ok(sig) + } + ast::ItemKind::Mod(ref _mod) => { + let mut text = "mod ".to_owned(); + let name = self.ident.to_string(); + let defs = vec![SigElement { + id: id_from_node_id(self.id, scx), + start: offset + text.len(), + end: offset + text.len() + name.len(), + }]; + text.push_str(&name); + // Could be either `mod foo;` or `mod foo { ... }`, but we'll just puck one. + text.push(';'); + + Ok(Signature { + text, + defs, + refs: vec![], + }) + } + ast::ItemKind::Ty(ref ty, ref generics) => { + let text = "type ".to_owned(); + let mut sig = name_and_generics(text, generics)?; + + sig.text.push_str(" = "); + let ty = ty.make(offset + sig.text.len(), id, scx)?; + sig.text.push_str(&ty.text); + sig.text.push(';'); + + Ok(merge_sigs(sig.text.clone(), vec![sig, ty])) + } + ast::ItemKind::Enum(_, ref generics) => { + let text = "enum ".to_owned(); + let mut sig = name_and_generics(text, generics)?; + sig.text.push_str(" {}"); + Ok(sig) + } + ast::ItemKind::Struct(_, ref generics) => { + let text = "struct ".to_owned(); + let mut sig = name_and_generics(text, generics)?; + sig.text.push_str(" {}"); + Ok(sig) + } + ast::ItemKind::Union(_, ref generics) => { + let text = "union ".to_owned(); + let mut sig = name_and_generics(text, generics)?; + sig.text.push_str(" {}"); + Ok(sig) + } + ast::ItemKind::Trait(unsafety, ref generics, ref bounds, _) => { + let mut text = String::new(); + if unsafety == ast::Unsafety::Unsafe { + text.push_str("unsafe "); + } + text.push_str("trait "); + let mut sig = name_and_generics(text, generics)?; + + if !bounds.is_empty() { + sig.text.push_str(": "); + sig.text.push_str(&pprust::bounds_to_string(bounds)); + } + // FIXME where clause + sig.text.push_str(" {}"); + + Ok(sig) + } + ast::ItemKind::DefaultImpl(unsafety, ref trait_ref) => { + let mut text = String::new(); + if unsafety == ast::Unsafety::Unsafe { + text.push_str("unsafe "); + } + text.push_str("impl "); + let trait_sig = trait_ref.path.make(offset + text.len(), id, scx)?; + text.push_str(&trait_sig.text); + text.push_str(" for .. {}"); + Ok(replace_text(trait_sig, text)) + } + ast::ItemKind::Impl(unsafety, + polarity, + defaultness, + ref generics, + ref opt_trait, + ref ty, + _) => { + let mut text = String::new(); + if let ast::Defaultness::Default = defaultness { + text.push_str("default "); + } + if unsafety == ast::Unsafety::Unsafe { + text.push_str("unsafe "); + } + text.push_str("impl"); + + let generics_sig = generics.make(offset + text.len(), id, scx)?; + text.push_str(&generics_sig.text); + + text.push(' '); + + let trait_sig = if let Some(ref t) = *opt_trait { + if polarity == ast::ImplPolarity::Negative { + text.push('!'); + } + let trait_sig = t.path.make(offset + text.len(), id, scx)?; + text.push_str(&trait_sig.text); + text.push_str(" for "); + trait_sig + } else { + text_sig(String::new()) + }; + + 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])) + + // FIXME where clause + } + ast::ItemKind::ForeignMod(_) => Err("extern mod"), + ast::ItemKind::GlobalAsm(_) => Err("glboal asm"), + ast::ItemKind::ExternCrate(_) => Err("extern crate"), + // FIXME should implement this (e.g., pub use). + ast::ItemKind::Use(_) => Err("import"), + ast::ItemKind::Mac(..) | + ast::ItemKind::MacroDef(_) => Err("Macro"), + } + } +} + +impl Sig for ast::Path { + fn make(&self, offset: usize, id: Option, scx: &SaveContext) -> Result { + let def = scx.get_path_def(id.ok_or("Missing id for Path")?); + let id = id_from_def_id(def.def_id()); + + let (name, start, end) = match def { + Def::AssociatedConst(..) | + Def::Variant(..) | + Def::VariantCtor(..) => { + let len = self.segments.len(); + if len < 2 { + return Err("Bad path"); + } + // FIXME: really we should descend into the generics here and add SigElements for + // them. + // FIXME: would be nice to have a def for the first path segment. + let seg1 = pprust::path_segment_to_string(&self.segments[len - 2]); + let seg2 = pprust::path_segment_to_string(&self.segments[len - 1]); + let start = offset + seg1.len() + 2; + (format!("{}::{}", seg1, seg2), start, start + seg2.len()) + } + _ => { + let name = pprust::path_segment_to_string(self.segments.last().ok_or("Bad path")?); + let end = offset + name.len(); + (name, offset, end) + } + }; + + Ok(Signature { + text: name, + defs: vec![], + refs: vec![SigElement { id, start, end }], + }) + } +} + +// This does not cover the where clause, which must be processed separately. +impl Sig for ast::Generics { + fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { + let total = self.lifetimes.len() + self.ty_params.len(); + if total == 0 { + return Ok(text_sig(String::new())); + } + + let mut text = "<".to_owned(); + + let mut defs = vec![]; + for l in &self.lifetimes { + let mut l_text = l.lifetime.ident.to_string(); + defs.push(SigElement { + id: id_from_node_id(l.lifetime.id, scx), + start: offset + text.len(), + end: offset + text.len() + l_text.len(), + }); + + if !l.bounds.is_empty() { + l_text.push_str(": "); + let bounds = l.bounds.iter().map(|l| l.ident.to_string()).collect::>().join(" + "); + l_text.push_str(&bounds); + // FIXME add lifetime bounds refs. + } + text.push_str(&l_text); + text.push(','); + } + for t in &self.ty_params { + let mut t_text = t.ident.to_string(); + defs.push(SigElement { + id: id_from_node_id(t.id, scx), + start: offset + text.len(), + end: offset + text.len() + t_text.len(), + }); + + if !t.bounds.is_empty() { + t_text.push_str(": "); + t_text.push_str(&pprust::bounds_to_string(&t.bounds)); + // FIXME descend properly into bounds. + } + text.push_str(&t_text); + text.push(','); + } + + text.push('>'); + Ok(Signature {text, defs, refs: vec![] }) + } +} + +// TODO impl items, trait items diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 073ededcb0ce7..34cda433d5250 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -370,6 +370,10 @@ pub fn path_to_string(p: &ast::Path) -> String { to_string(|s| s.print_path(p, false, 0, false)) } +pub fn path_segment_to_string(p: &ast::PathSegment) -> String { + to_string(|s| s.print_path_segment(p, false)) +} + pub fn ident_to_string(id: ast::Ident) -> String { to_string(|s| s.print_ident(id)) } @@ -2359,18 +2363,27 @@ impl<'a> State<'a> { if i > 0 { word(&mut self.s, "::")? } - if segment.identifier.name != keywords::CrateRoot.name() && - segment.identifier.name != "$crate" { - self.print_ident(segment.identifier)?; - if let Some(ref parameters) = segment.parameters { - self.print_path_parameters(parameters, colons_before_params)?; - } - } + self.print_path_segment(segment, colons_before_params)?; } Ok(()) } + fn print_path_segment(&mut self, + segment: &ast::PathSegment, + colons_before_params: bool) + -> io::Result<()> + { + if segment.identifier.name != keywords::CrateRoot.name() && + segment.identifier.name != "$crate" { + self.print_ident(segment.identifier)?; + if let Some(ref parameters) = segment.parameters { + self.print_path_parameters(parameters, colons_before_params)?; + } + } + Ok(()) + } + fn print_qpath(&mut self, path: &ast::Path, qself: &ast::QSelf, From 0058fdd110bd98a8e3e8b487247bef5f4e6cb618 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 30 May 2017 12:01:48 +1200 Subject: [PATCH 2/9] Update rls-data --- src/Cargo.lock | 6 +++--- src/librustc_save_analysis/Cargo.toml | 2 +- src/librustc_save_analysis/json_dumper.rs | 3 --- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 8bf4b6ad3e0c7..7718dff3b837e 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1049,7 +1049,7 @@ dependencies = [ [[package]] name = "rls-data" -version = "0.4.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1372,7 +1372,7 @@ name = "rustc_save_analysis" version = "0.0.0" dependencies = [ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-data 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-data 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2077,7 +2077,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" "checksum rls-analysis 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d77d58e8933752142b5b92e3f8ba6d6f1630be6da5627c492268a43f79ffbda" "checksum rls-data 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fc4277ce3c57f456b11fe3145b181a844a25201bab5cbaa1978457e6e2f27d47" -"checksum rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "374a8fad31cc0681a7bfd8a04079dd4afd0e981d34e18a171b1a467445bdf51e" +"checksum rls-data 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e2087477364c34faca86c2476765deb1185dbae3c598cfb1eb040f3a74d22b5" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" "checksum rls-vfs 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ace07060dd154731b39254864245cbdd33c8f5f64fe1f630a089c72e2468f854" "checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95" diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml index 6d04bff82829a..53a82cf73e95b 100644 --- a/src/librustc_save_analysis/Cargo.toml +++ b/src/librustc_save_analysis/Cargo.toml @@ -14,7 +14,7 @@ rustc = { path = "../librustc" } rustc_typeck = { path = "../librustc_typeck" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } -rls-data = "0.3" +rls-data = "0.6" rls-span = "0.4" # FIXME(#40527) should move rustc serialize out of tree rustc-serialize = "0.3" diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index eaa0c0825f0e9..a315cca9f4d81 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -484,10 +484,7 @@ impl Into for InheritanceData { impl Into for external_data::Signature { fn into(self) -> Signature { Signature { - span: self.span, text: self.text, - ident_start: self.ident_start, - ident_end: self.ident_end, defs: self.defs.into_iter().map(|s| s.into()).collect(), refs: self.refs.into_iter().map(|s| s.into()).collect(), } From a2a999f0356d037d09b7cd1d3b5b3011d6b810db Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 31 May 2017 15:59:48 +1200 Subject: [PATCH 3/9] Use the new signature stuff And fix a couple of bugs --- src/librustc_save_analysis/data.rs | 41 ++-------- src/librustc_save_analysis/dump_visitor.rs | 37 ++++----- src/librustc_save_analysis/external_data.rs | 65 +++++---------- src/librustc_save_analysis/json_api_dumper.rs | 14 ++-- src/librustc_save_analysis/json_dumper.rs | 43 +++------- src/librustc_save_analysis/lib.rs | 79 ++++--------------- src/librustc_save_analysis/sig.rs | 27 +++++-- 7 files changed, 95 insertions(+), 211 deletions(-) diff --git a/src/librustc_save_analysis/data.rs b/src/librustc_save_analysis/data.rs index cac1a2e3c5af1..e15e3f6e79e26 100644 --- a/src/librustc_save_analysis/data.rs +++ b/src/librustc_save_analysis/data.rs @@ -18,7 +18,7 @@ use rustc::hir::def_id::{CrateNum, DefId}; use syntax::ast::{self, Attribute, NodeId}; use syntax_pos::Span; -use rls_data::ExternalCrateData; +use rls_data::{ExternalCrateData, Signature}; pub struct CrateData { pub name: String, @@ -129,7 +129,7 @@ pub struct EnumData { pub variants: Vec, pub visibility: Visibility, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -165,7 +165,7 @@ pub struct FunctionData { pub visibility: Visibility, pub parent: Option, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -251,7 +251,7 @@ pub struct MethodData { pub parent: Option, pub visibility: Visibility, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -292,7 +292,7 @@ pub struct StructData { pub fields: Vec, pub visibility: Visibility, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -307,7 +307,7 @@ pub struct StructVariantData { pub scope: NodeId, pub parent: Option, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -322,7 +322,7 @@ pub struct TraitData { pub items: Vec, pub visibility: Visibility, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -337,7 +337,7 @@ pub struct TupleVariantData { pub scope: NodeId, pub parent: Option, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -419,28 +419,3 @@ 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)] -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, - pub refs: Vec, -} - -/// An element of a signature. `start` and `end` are byte offsets into the `text` -/// of the parent `Signature`. -#[derive(Clone, Debug)] -pub struct SigElement { - pub id: DefId, - pub start: usize, - pub end: usize, -} diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index a95236e2a5072..568670cbdb611 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -48,12 +48,13 @@ use syntax::ptr::P; use syntax::codemap::Spanned; use syntax_pos::*; -use super::{escape, generated_code, SaveContext, PathCollector, docs_for_attrs}; -use super::data::*; -use super::dump::Dump; -use super::external_data::{Lower, make_def_id}; -use super::span_utils::SpanUtils; -use super::recorder; +use {escape, generated_code, SaveContext, PathCollector, docs_for_attrs}; +use data::*; +use dump::Dump; +use external_data::{Lower, make_def_id}; +use recorder; +use span_utils::SpanUtils; +use sig; use rls_data::ExternalCrateData; @@ -646,7 +647,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { fields: fields, visibility: From::from(&item.vis), docs: docs_for_attrs(&item.attrs), - sig: self.save_ctxt.sig_base(item), + sig: sig::item_signature(item, &self.save_ctxt), attributes: item.attrs.clone(), }.lower(self.tcx)); } @@ -679,18 +680,6 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { 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); @@ -712,7 +701,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { scope: enum_data.scope, parent: Some(make_def_id(item.id, &self.tcx.hir)), docs: docs_for_attrs(&variant.node.attrs), - sig: sig, + // TODO + sig: None, attributes: variant.node.attrs.clone(), }.lower(self.tcx)); } @@ -739,7 +729,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { scope: enum_data.scope, parent: Some(make_def_id(item.id, &self.tcx.hir)), docs: docs_for_attrs(&variant.node.attrs), - sig: sig, + // TODO + sig: None, attributes: variant.node.attrs.clone(), }.lower(self.tcx)); } @@ -811,7 +802,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { 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), + sig: sig::item_signature(item, &self.save_ctxt), attributes: item.attrs.clone(), }.lower(self.tcx)); } @@ -1369,7 +1360,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, visibility: From::from(&item.vis), parent: None, docs: docs_for_attrs(&item.attrs), - sig: Some(self.save_ctxt.sig_base(item)), + sig: sig::item_signature(item, &self.save_ctxt), attributes: item.attrs.clone(), }.lower(self.tcx)); } diff --git a/src/librustc_save_analysis/external_data.rs b/src/librustc_save_analysis/external_data.rs index 02441a0587eb6..245a3bcc61795 100644 --- a/src/librustc_save_analysis/external_data.rs +++ b/src/librustc_save_analysis/external_data.rs @@ -16,9 +16,9 @@ use syntax::codemap::CodeMap; use syntax::print::pprust; use syntax_pos::Span; -use data::{self, Visibility, SigElement}; +use data::{self, Visibility}; -use rls_data::{SpanData, CratePreludeData, Attribute}; +use rls_data::{SpanData, CratePreludeData, Attribute, Signature}; use rls_span::{Column, Row}; // FIXME: this should be pub(crate), but the current snapshot doesn't allow it yet @@ -103,7 +103,7 @@ pub struct EnumData { pub variants: Vec, pub visibility: Visibility, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -121,7 +121,7 @@ impl Lower for data::EnumData { variants: self.variants.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(), visibility: self.visibility, docs: self.docs, - sig: self.sig.lower(tcx), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -186,7 +186,7 @@ pub struct FunctionData { pub visibility: Visibility, pub parent: Option, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -205,7 +205,7 @@ impl Lower for data::FunctionData { visibility: self.visibility, parent: self.parent, docs: self.docs, - sig: self.sig.lower(tcx), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -355,7 +355,7 @@ pub struct MethodData { pub visibility: Visibility, pub parent: Option, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -374,7 +374,7 @@ impl Lower for data::MethodData { visibility: self.visibility, parent: self.parent, docs: self.docs, - sig: self.sig.lower(tcx), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -410,7 +410,7 @@ impl Lower for data::ModData { items: self.items.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(), visibility: self.visibility, docs: self.docs, - sig: self.sig.map(|s| s.lower(tcx)), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -450,7 +450,7 @@ pub struct StructData { pub fields: Vec, pub visibility: Visibility, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -469,7 +469,7 @@ impl Lower for data::StructData { fields: self.fields.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(), visibility: self.visibility, docs: self.docs, - sig: self.sig.lower(tcx), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -486,7 +486,7 @@ pub struct StructVariantData { pub scope: DefId, pub parent: Option, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -504,7 +504,7 @@ impl Lower for data::StructVariantData { scope: make_def_id(self.scope, &tcx.hir), parent: self.parent, docs: self.docs, - sig: self.sig.lower(tcx), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -521,7 +521,7 @@ pub struct TraitData { pub items: Vec, pub visibility: Visibility, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -539,7 +539,7 @@ impl Lower for data::TraitData { items: self.items.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(), visibility: self.visibility, docs: self.docs, - sig: self.sig.lower(tcx), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -556,7 +556,7 @@ pub struct TupleVariantData { pub scope: DefId, pub parent: Option, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -574,7 +574,7 @@ impl Lower for data::TupleVariantData { scope: make_def_id(self.scope, &tcx.hir), parent: self.parent, docs: self.docs, - sig: self.sig.lower(tcx), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -608,7 +608,7 @@ impl Lower for data::TypeDefData { visibility: self.visibility, parent: self.parent, docs: self.docs, - sig: self.sig.map(|s| s.lower(tcx)), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -718,7 +718,7 @@ impl Lower for data::VariableData { parent: self.parent, visibility: self.visibility, docs: self.docs, - sig: self.sig.map(|s| s.lower(tcx)), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -746,30 +746,3 @@ impl Lower for data::VariableRefData { } } } - -#[derive(Clone, Debug)] -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, - pub refs: Vec, -} - -impl Lower for data::Signature { - type Target = Signature; - - fn lower(self, tcx: TyCtxt) -> Signature { - Signature { - span: span_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, - } - } -} diff --git a/src/librustc_save_analysis/json_api_dumper.rs b/src/librustc_save_analysis/json_api_dumper.rs index 49b14f5eca072..1f65efbf9dcd0 100644 --- a/src/librustc_save_analysis/json_api_dumper.rs +++ b/src/librustc_save_analysis/json_api_dumper.rs @@ -133,7 +133,7 @@ impl Into> for EnumData { children: self.variants.into_iter().map(|id| id_from_def_id(id)).collect(), decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: vec![], }), _ => None, @@ -154,7 +154,7 @@ impl Into> for TupleVariantData { children: vec![], decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: vec![], }) } @@ -172,7 +172,7 @@ impl Into> for StructVariantData { children: vec![], decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: vec![], }) } @@ -191,7 +191,7 @@ impl Into> for StructData { children: self.fields.into_iter().map(|id| id_from_def_id(id)).collect(), decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: vec![], }), _ => None, @@ -212,7 +212,7 @@ impl Into> for TraitData { parent: None, decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: vec![], }), _ => None, @@ -233,7 +233,7 @@ impl Into> for FunctionData { parent: self.parent.map(|id| id_from_def_id(id)), decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: vec![], }), _ => None, @@ -254,7 +254,7 @@ impl Into> for MethodData { parent: self.parent.map(|id| id_from_def_id(id)), decl_id: self.decl_id.map(|id| id_from_def_id(id)), docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: vec![], }), _ => None, diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index a315cca9f4d81..2832eb505eca4 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -14,12 +14,11 @@ use rustc::hir::def_id::DefId; use rustc_serialize::json::as_json; use rls_data::{self, Id, Analysis, Import, ImportKind, Def, DefKind, Ref, RefKind, MacroRef, - Relation, RelationKind, Signature, SigElement, CratePreludeData}; + Relation, RelationKind, CratePreludeData}; use rls_span::{Column, Row}; -use external_data; use external_data::*; -use data::{self, VariableKind}; +use data::VariableKind; use dump::Dump; pub struct JsonDumper { @@ -121,7 +120,7 @@ impl<'b, O: DumpOutput + 'b> Dump for JsonDumper { children: data.items.into_iter().map(|id| id_from_def_id(id)).collect(), decl_id: None, docs: data.docs, - sig: data.sig.map(|s| s.into()), + sig: data.sig, attributes: data.attributes.into_iter().map(|a| a.into()).collect(), }; if def.span.file_name.to_str().unwrap() != def.value { @@ -220,7 +219,7 @@ impl Into for EnumData { children: self.variants.into_iter().map(|id| id_from_def_id(id)).collect(), decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: self.attributes, } } @@ -239,7 +238,7 @@ impl Into for TupleVariantData { children: vec![], decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: self.attributes, } } @@ -257,7 +256,7 @@ impl Into for StructVariantData { children: vec![], decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: self.attributes, } } @@ -275,7 +274,7 @@ impl Into for StructData { children: self.fields.into_iter().map(|id| id_from_def_id(id)).collect(), decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: self.attributes, } } @@ -293,7 +292,7 @@ impl Into for TraitData { children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(), decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: self.attributes, } } @@ -311,7 +310,7 @@ impl Into for FunctionData { children: vec![], decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: self.attributes, } } @@ -329,7 +328,7 @@ impl Into for MethodData { children: vec![], decl_id: self.decl_id.map(|id| id_from_def_id(id)), docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: self.attributes, } } @@ -365,7 +364,7 @@ impl Into for TypeDefData { children: vec![], decl_id: None, docs: String::new(), - sig: self.sig.map(|s| s.into()), + sig: self.sig, attributes: self.attributes, } } @@ -480,23 +479,3 @@ impl Into for InheritanceData { } } } - -impl Into for external_data::Signature { - fn into(self) -> Signature { - Signature { - text: self.text, - defs: self.defs.into_iter().map(|s| s.into()).collect(), - refs: self.refs.into_iter().map(|s| s.into()).collect(), - } - } -} - -impl Into for data::SigElement { - fn into(self) -> SigElement { - SigElement { - id: id_from_def_id(self.id), - start: self.start, - end: self.end, - } - } -} diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 655901aa8591c..06309a4f79e75 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -141,7 +141,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { visibility: From::from(&item.vis), parent: None, docs: docs_for_attrs(&item.attrs), - sig: self.sig_base_extern(item), + // TODO + sig: None, attributes: item.attrs.clone(), })) } @@ -161,7 +162,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { type_value: ty_to_string(ty), visibility: From::from(&item.vis), docs: docs_for_attrs(&item.attrs), - sig: Some(self.sig_base_extern(item)), + // TODO + sig: None, attributes: item.attrs.clone(), })) } @@ -187,7 +189,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { visibility: From::from(&item.vis), parent: None, docs: docs_for_attrs(&item.attrs), - sig: self.sig_base(item), + sig: sig::item_signature(item, self), attributes: item.attrs.clone(), })) } @@ -216,7 +218,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { type_value: ty_to_string(&typ), visibility: From::from(&item.vis), docs: docs_for_attrs(&item.attrs), - sig: Some(self.sig_base(item)), + sig: sig::item_signature(item, self), attributes: item.attrs.clone(), })) } @@ -236,7 +238,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { type_value: ty_to_string(&typ), visibility: From::from(&item.vis), docs: docs_for_attrs(&item.attrs), - sig: Some(self.sig_base(item)), + sig: sig::item_signature(item, self), attributes: item.attrs.clone(), })) } @@ -259,7 +261,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { items: m.items.iter().map(|i| i.id).collect(), visibility: From::from(&item.vis), docs: docs_for_attrs(&item.attrs), - sig: Some(self.sig_base(item)), + sig: sig::item_signature(item, self), attributes: item.attrs.clone(), })) } @@ -283,7 +285,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { 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), + sig: sig::item_signature(item, self), attributes: item.attrs.clone(), })) } @@ -347,18 +349,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let def_id = self.tcx.hir.local_def_id(field.id); let typ = self.tcx.type_of(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, @@ -371,7 +361,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { type_value: typ, visibility: From::from(&field.vis), docs: docs_for_attrs(&field.attrs), - sig: Some(sig), + // TODO + sig: None, attributes: field.attrs.clone(), }) } else { @@ -460,22 +451,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { 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, + name: name.to_string(), qualname: qualname, declaration: decl_id, span: sub_span.unwrap(), @@ -485,7 +463,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { visibility: vis, parent: parent_scope, docs: docs, - sig: sig, + // TODO + sig: None, attributes: attributes, }) } @@ -787,36 +766,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } - 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: Span { hi: item.span.lo + BytePos(text.len() as u32), ..item.span }, - text: text, - ident_start: ident_start, - ident_end: ident_end, - defs: vec![], - refs: vec![], - } - } - - fn sig_base_extern(&self, item: &ast::ForeignItem) -> 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: Span { hi: item.span.lo + BytePos(text.len() as u32), ..item.span }, - 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.hir.get_enclosing_scope(id).unwrap_or(CRATE_NODE_ID) diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 945f405659d53..0dd0112a1b692 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -22,6 +22,10 @@ use syntax::ast::{self, NodeId}; use syntax::print::pprust; +pub fn item_signature(item: &ast::Item, scx: &SaveContext) -> Option { + item.make(0, None, scx).ok() +} + // TODO dup from json_dumper fn id_from_def_id(id: DefId) -> Id { Id { @@ -246,8 +250,8 @@ impl Sig for ast::Item { let name = self.ident.to_string(); let def = SigElement { id: id_from_node_id(self.id, scx), - start: offset + 5, - end: offset + 5 + name.len(), + start: offset + text.len(), + end: offset + text.len() + name.len(), }; text.push_str(&name); let generics: Signature = generics.make(offset + text.len(), id, scx)?; @@ -336,7 +340,6 @@ impl Sig for ast::Item { sig.text.push_str(" -> "); let nested = t.make(offset + sig.text.len(), None, scx)?; sig.text.push_str(&nested.text); - sig.text.push(','); sig.defs.extend(nested.defs.into_iter()); sig.refs.extend(nested.refs.into_iter()); } @@ -473,10 +476,23 @@ impl Sig for ast::Item { impl Sig for ast::Path { fn make(&self, offset: usize, id: Option, scx: &SaveContext) -> Result { + // if generated_code(span) { + // return Err("Generated code"); + // } + let def = scx.get_path_def(id.ok_or("Missing id for Path")?); - let id = id_from_def_id(def.def_id()); let (name, start, end) = match def { + Def::Label(..) | + Def::PrimTy(..) | + Def::SelfTy(..) | + Def::Err => { + return Ok(Signature { + text: pprust::path_to_string(self), + defs: vec![], + refs: vec![], + }) + } Def::AssociatedConst(..) | Def::Variant(..) | Def::VariantCtor(..) => { @@ -499,6 +515,7 @@ impl Sig for ast::Path { } }; + let id = id_from_def_id(def.def_id()); Ok(Signature { text: name, defs: vec![], @@ -557,4 +574,4 @@ impl Sig for ast::Generics { } } -// TODO impl items, trait items +// TODO impl items, trait items, fields, extern items, enum variant From 35abf139a2e43b8695d907ab62bc2bb46bc8bcc3 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 31 May 2017 16:13:27 +1200 Subject: [PATCH 4/9] Small refactoring + docs --- src/librustc_save_analysis/json_api_dumper.rs | 2 +- src/librustc_save_analysis/json_dumper.rs | 11 +---- src/librustc_save_analysis/lib.rs | 16 ++++++- src/librustc_save_analysis/sig.rs | 47 +++++++++++-------- 4 files changed, 45 insertions(+), 31 deletions(-) diff --git a/src/librustc_save_analysis/json_api_dumper.rs b/src/librustc_save_analysis/json_api_dumper.rs index 1f65efbf9dcd0..5c6876461346e 100644 --- a/src/librustc_save_analysis/json_api_dumper.rs +++ b/src/librustc_save_analysis/json_api_dumper.rs @@ -15,7 +15,7 @@ use rustc_serialize::json::as_json; use external_data::*; use data::{VariableKind, Visibility}; use dump::Dump; -use json_dumper::id_from_def_id; +use id_from_def_id; use rls_data::{Analysis, Import, ImportKind, Def, DefKind, CratePreludeData}; diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index 2832eb505eca4..58df612c687c3 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -10,7 +10,6 @@ use std::io::Write; -use rustc::hir::def_id::DefId; use rustc_serialize::json::as_json; use rls_data::{self, Id, Analysis, Import, ImportKind, Def, DefKind, Ref, RefKind, MacroRef, @@ -20,6 +19,7 @@ use rls_span::{Column, Row}; use external_data::*; use data::VariableKind; use dump::Dump; +use id_from_def_id; pub struct JsonDumper { result: Analysis, @@ -163,15 +163,6 @@ impl<'b, O: DumpOutput + 'b> Dump for JsonDumper { // method, but not the supplied method). In both cases, we are currently // ignoring it. -// DefId::index is a newtype and so the JSON serialisation is ugly. Therefore -// we use our own Id which is the same, but without the newtype. -pub fn id_from_def_id(id: DefId) -> Id { - Id { - krate: id.krate.as_u32(), - index: id.index.as_u32(), - } -} - impl Into for ExternCrateData { fn into(self) -> Import { Import { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 06309a4f79e75..b6fafe3ee52b7 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -1026,6 +1026,20 @@ fn escape(s: String) -> String { // Helper function to determine if a span came from a // macro expansion or syntax extension. -pub fn generated_code(span: Span) -> bool { +fn generated_code(span: Span) -> bool { span.ctxt != NO_EXPANSION || span == DUMMY_SP } + +// DefId::index is a newtype and so the JSON serialisation is ugly. Therefore +// we use our own Id which is the same, but without the newtype. +fn id_from_def_id(id: DefId) -> rls_data::Id { + rls_data::Id { + krate: id.krate.as_u32(), + index: id.index.as_u32(), + } +} + +fn id_from_node_id(id: NodeId, scx: &SaveContext) -> rls_data::Id { + let def_id = scx.tcx.hir.local_def_id(id); + id_from_def_id(def_id) +} diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 0dd0112a1b692..6b734eb524800 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -8,16 +8,38 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME? None of these include visibility info. -// Large outstanding things - where clauses, defs/refs for generics -// paresable - each sig ends with `;` of ` {}` +// A signature is a string representation of an item's type signature, excluding +// any body. It also includes ids for any defs or refs in the signature. For +// example: +// +// ``` +// fn foo(x: String) { +// println!("{}", x); +// } +// ``` +// The signature string is something like "fn foo(x: String) {}" and the signature +// will have defs for `foo` and `x` and a ref for `String`. +// +// All signature text should parse in the correct context (i.e., in a module or +// impl, etc.). Clients may want to trim trailing `{}` or `;`. The text of a +// signature is not guaranteed to be stable (it may improve or change as the +// syntax changes, or whitespace or punctuation may change). It is also likely +// not to be pretty - no attempt is made to prettify the text. It is recommended +// that clients run the text through Rustfmt. +// +// This module generates Signatures for items by walking the AST and looking up +// references. +// +// Signatures do not include visibility info. I'm not sure if this is a feature +// or an ommission (FIXME). +// +// FIXME where clauses need implementing, defs/refs in generics are mostly missing. -use SaveContext; +use {SaveContext, id_from_def_id, id_from_node_id}; -use rls_data::{Signature, SigElement, Id}; +use rls_data::{Signature, SigElement}; use rustc::hir::def::Def; -use rustc::hir::def_id::DefId; use syntax::ast::{self, NodeId}; use syntax::print::pprust; @@ -26,19 +48,6 @@ pub fn item_signature(item: &ast::Item, scx: &SaveContext) -> Option item.make(0, None, scx).ok() } -// TODO dup from json_dumper -fn id_from_def_id(id: DefId) -> Id { - Id { - krate: id.krate.as_u32(), - index: id.index.as_u32(), - } -} - -fn id_from_node_id(id: NodeId, scx: &SaveContext) -> Id { - let def_id = scx.tcx.hir.local_def_id(id); - id_from_def_id(def_id) -} - type Result = ::std::result::Result; trait Sig { From 5ebb0e2498edc84093003d8053a7d11e51536120 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 5 Jun 2017 16:42:39 +1200 Subject: [PATCH 5/9] Implement a bunch more signature functions --- src/librustc_save_analysis/dump_visitor.rs | 6 +- src/librustc_save_analysis/lib.rs | 9 +- src/librustc_save_analysis/sig.rs | 251 +++++++++++++++++++-- 3 files changed, 231 insertions(+), 35 deletions(-) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 568670cbdb611..61fc9a9adfb09 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -701,8 +701,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { scope: enum_data.scope, parent: Some(make_def_id(item.id, &self.tcx.hir)), docs: docs_for_attrs(&variant.node.attrs), - // TODO - sig: None, + sig: sig::variant_signature(variant, &self.save_ctxt), attributes: variant.node.attrs.clone(), }.lower(self.tcx)); } @@ -729,8 +728,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { scope: enum_data.scope, parent: Some(make_def_id(item.id, &self.tcx.hir)), docs: docs_for_attrs(&variant.node.attrs), - // TODO - sig: None, + sig: sig::variant_signature(variant, &self.save_ctxt), attributes: variant.node.attrs.clone(), }.lower(self.tcx)); } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index b6fafe3ee52b7..8e280377ce2d6 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -141,8 +141,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { visibility: From::from(&item.vis), parent: None, docs: docs_for_attrs(&item.attrs), - // TODO - sig: None, + sig: sig::foreign_item_signature(item, self), attributes: item.attrs.clone(), })) } @@ -162,8 +161,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { type_value: ty_to_string(ty), visibility: From::from(&item.vis), docs: docs_for_attrs(&item.attrs), - // TODO - sig: None, + sig: sig::foreign_item_signature(item, self), attributes: item.attrs.clone(), })) } @@ -361,8 +359,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { type_value: typ, visibility: From::from(&field.vis), docs: docs_for_attrs(&field.attrs), - // TODO - sig: None, + sig: sig::field_signature(field, self), attributes: field.attrs.clone(), }) } else { diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 6b734eb524800..b2a62038dfc15 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -48,6 +48,21 @@ pub fn item_signature(item: &ast::Item, scx: &SaveContext) -> Option item.make(0, None, scx).ok() } +pub fn foreign_item_signature(item: &ast::ForeignItem, scx: &SaveContext) -> Option { + item.make(0, None, scx).ok() +} + +/// Signature for a struct or tuple field declaration. +/// Does not include a trailing comma. +pub fn field_signature(field: &ast::StructField, scx: &SaveContext) -> Option { + field.make(0, None, scx).ok() +} + +/// Does not include a trailing comma. +pub fn variant_signature(variant: &ast::Variant, scx: &SaveContext) -> Option { + variant.node.make(0, None, scx).ok() +} + type Result = ::std::result::Result; trait Sig { @@ -255,20 +270,6 @@ impl Sig for ast::Item { fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { let id = Some(self.id); - let name_and_generics = |mut text: String, generics: &ast::Generics| -> Result { - let name = self.ident.to_string(); - let def = SigElement { - id: id_from_node_id(self.id, scx), - start: offset + text.len(), - end: offset + text.len() + name.len(), - }; - text.push_str(&name); - let generics: Signature = generics.make(offset + text.len(), id, scx)?; - // FIXME where clause - let text = format!("{}{}", text, generics.text); - Ok(extend_sig(generics, text, vec![def], vec![])) - }; - match self.node { ast::ItemKind::Static(ref ty, m, ref expr) => { let mut text = "static ".to_owned(); @@ -330,7 +331,12 @@ impl Sig for ast::Item { } text.push_str("fn "); - let mut sig = name_and_generics(text, generics)?; + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; sig.text.push('('); for i in &decl.inputs { @@ -352,6 +358,7 @@ impl Sig for ast::Item { sig.defs.extend(nested.defs.into_iter()); sig.refs.extend(nested.refs.into_iter()); } + sig.text.push_str(" {}"); Ok(sig) } @@ -375,7 +382,12 @@ impl Sig for ast::Item { } ast::ItemKind::Ty(ref ty, ref generics) => { let text = "type ".to_owned(); - let mut sig = name_and_generics(text, generics)?; + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; sig.text.push_str(" = "); let ty = ty.make(offset + sig.text.len(), id, scx)?; @@ -386,19 +398,34 @@ impl Sig for ast::Item { } ast::ItemKind::Enum(_, ref generics) => { let text = "enum ".to_owned(); - let mut sig = name_and_generics(text, generics)?; + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; sig.text.push_str(" {}"); Ok(sig) } ast::ItemKind::Struct(_, ref generics) => { let text = "struct ".to_owned(); - let mut sig = name_and_generics(text, generics)?; + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; sig.text.push_str(" {}"); Ok(sig) } ast::ItemKind::Union(_, ref generics) => { let text = "union ".to_owned(); - let mut sig = name_and_generics(text, generics)?; + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; sig.text.push_str(" {}"); Ok(sig) } @@ -408,7 +435,12 @@ impl Sig for ast::Item { text.push_str("unsafe "); } text.push_str("trait "); - let mut sig = name_and_generics(text, generics)?; + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; if !bounds.is_empty() { sig.text.push_str(": "); @@ -485,10 +517,6 @@ impl Sig for ast::Item { impl Sig for ast::Path { fn make(&self, offset: usize, id: Option, scx: &SaveContext) -> Result { - // if generated_code(span) { - // return Err("Generated code"); - // } - let def = scx.get_path_def(id.ok_or("Missing id for Path")?); let (name, start, end) = match def { @@ -583,4 +611,177 @@ impl Sig for ast::Generics { } } -// TODO impl items, trait items, fields, extern items, enum variant +impl Sig for ast::StructField { + fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { + let mut text = String::new(); + let mut defs = None; + if let Some(ref ident) = self.ident { + text.push_str(&ident.to_string()); + defs = Some(SigElement { + id: id_from_node_id(self.id, scx), + start: offset, + end: offset + text.len(), + }); + text.push_str(": "); + } + + let mut ty_sig = self.ty.make(offset + text.len(), Some(self.id), scx)?; + text.push_str(&ty_sig.text); + ty_sig.text = text; + ty_sig.defs.extend(defs.into_iter()); + Ok(ty_sig) + } +} + + +impl Sig for ast::Variant_ { + fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { + let mut text = self.name.to_string(); + match self.data { + ast::VariantData::Struct(ref fields, id) => { + let name_def = SigElement { + id: id_from_node_id(id, scx), + start: offset, + end: offset + text.len(), + }; + text.push_str(" { "); + let mut defs = vec![name_def]; + let mut refs = vec![]; + for f in fields { + let field_sig = f.make(offset + text.len(), Some(id), scx)?; + text.push_str(&field_sig.text); + text.push_str(", "); + defs.extend(field_sig.defs.into_iter()); + refs.extend(field_sig.refs.into_iter()); + } + text.push('}'); + Ok(Signature { + text, + defs: defs, + refs: refs, + }) + } + ast::VariantData::Tuple(ref fields, id) => { + let name_def = SigElement { + id: id_from_node_id(id, scx), + start: offset, + end: offset + text.len(), + }; + text.push('('); + let mut defs = vec![name_def]; + let mut refs = vec![]; + for f in fields { + let field_sig = f.make(offset + text.len(), Some(id), scx)?; + text.push_str(&field_sig.text); + text.push_str(", "); + defs.extend(field_sig.defs.into_iter()); + refs.extend(field_sig.refs.into_iter()); + } + text.push(')'); + Ok(Signature { + text, + defs: defs, + refs: refs, + }) + } + ast::VariantData::Unit(id) => { + let name_def = SigElement { + id: id_from_node_id(id, scx), + start: offset, + end: offset + text.len(), + }; + Ok(Signature { + text, + defs: vec![name_def], + refs: vec![], + }) + } + } + } +} + +impl Sig for ast::ForeignItem { + fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { + let id = Some(self.id); + match self.node { + ast::ForeignItemKind::Fn(ref decl, ref generics) => { + let mut text = String::new(); + text.push_str("fn "); + + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; + + sig.text.push('('); + for i in &decl.inputs { + // FIXME should 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(offset + 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) = decl.output { + sig.text.push_str(" -> "); + let nested = t.make(offset + 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(';'); + + Ok(sig) + } + ast::ForeignItemKind::Static(ref ty, m) => { + let mut text = "static ".to_owned(); + if m { + text.push_str("mut "); + } + let name = self.ident.to_string(); + let defs = vec![SigElement { + id: id_from_node_id(self.id, scx), + start: offset + text.len(), + end: offset + text.len() + name.len(), + }]; + text.push_str(&name); + text.push_str(": "); + + let ty_sig = ty.make(offset + text.len(), id, scx)?; + text.push(';'); + + Ok(extend_sig(ty_sig, text, defs, vec![])) + } + } + } +} + +fn name_and_generics(mut text: String, + offset: usize, + generics: &ast::Generics, + id: NodeId, + name: ast::Ident, + scx: &SaveContext) + -> Result { + let name = name.to_string(); + let def = SigElement { + id: id_from_node_id(id, scx), + start: offset + text.len(), + end: offset + text.len() + name.len(), + }; + text.push_str(&name); + let generics: Signature = generics.make(offset + text.len(), Some(id), scx)?; + // FIXME where clause + let text = format!("{}{}", text, generics.text); + Ok(extend_sig(generics, text, vec![def], vec![])) +} + + +// TODO impl items, trait items +// for impl/trait sigs - function for each kind, rather than use trait. From cb7fcdd520d8297bbb2bea6e0a017d1b5df0b819 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 6 Jun 2017 12:19:54 +1200 Subject: [PATCH 6/9] Impl and trait item sigs --- src/librustc_save_analysis/dump_visitor.rs | 45 +++--- src/librustc_save_analysis/lib.rs | 8 +- src/librustc_save_analysis/sig.rs | 152 ++++++++++++++++++++- 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 61fc9a9adfb09..ea346d99e31b5 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 8e280377ce2d6..4802494f08ead 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 { + pub fn get_method_data(&self, + id: ast::NodeId, + name: ast::Name, + span: Span) + -> Option { // 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 b2a62038dfc15..1d03ab1383af1 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 Option { + 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 { + 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 { + make_assoc_type_signature(id, ident, bounds, default, scx).ok() +} + type Result = ::std::result::Result; 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::>().join(" + "); + let bounds = l.bounds.iter().map(|l| { + l.ident.to_string() + }).collect::>().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) +} From d438b8180c52b2cb85c2f4f29ee09c88e5eba0da Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 6 Jun 2017 16:12:11 +1200 Subject: [PATCH 7/9] Fix a bug where Json API save-analysis was not labelled as such --- src/librustc_save_analysis/json_api_dumper.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc_save_analysis/json_api_dumper.rs b/src/librustc_save_analysis/json_api_dumper.rs index 5c6876461346e..bddee6460ff9c 100644 --- a/src/librustc_save_analysis/json_api_dumper.rs +++ b/src/librustc_save_analysis/json_api_dumper.rs @@ -17,7 +17,7 @@ use data::{VariableKind, Visibility}; use dump::Dump; use id_from_def_id; -use rls_data::{Analysis, Import, ImportKind, Def, DefKind, CratePreludeData}; +use rls_data::{Analysis, Import, ImportKind, Def, DefKind, CratePreludeData, Format}; // A dumper to dump a restricted set of JSON information, designed for use with @@ -33,7 +33,9 @@ pub struct JsonApiDumper<'b, W: Write + 'b> { impl<'b, W: Write> JsonApiDumper<'b, W> { pub fn new(writer: &'b mut W) -> JsonApiDumper<'b, W> { - JsonApiDumper { output: writer, result: Analysis::new() } + let mut result = Analysis::new(); + result.kind = Format::JsonApi; + JsonApiDumper { output: writer, result } } } From 34bd80a782ffc75a61a31794fa1fb8b7c48eb765 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 12 Jun 2017 14:29:59 +1200 Subject: [PATCH 8/9] Fix rebasing error --- src/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 7718dff3b837e..efbbe36c981a8 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1040,7 +1040,7 @@ dependencies = [ [[package]] name = "rls-data" -version = "0.3.1" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2076,7 +2076,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" "checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" "checksum rls-analysis 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d77d58e8933752142b5b92e3f8ba6d6f1630be6da5627c492268a43f79ffbda" -"checksum rls-data 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fc4277ce3c57f456b11fe3145b181a844a25201bab5cbaa1978457e6e2f27d47" +"checksum rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "374a8fad31cc0681a7bfd8a04079dd4afd0e981d34e18a171b1a467445bdf51e" "checksum rls-data 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e2087477364c34faca86c2476765deb1185dbae3c598cfb1eb040f3a74d22b5" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" "checksum rls-vfs 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ace07060dd154731b39254864245cbdd33c8f5f64fe1f630a089c72e2468f854" From ffd83fdf7deacc8f985dab0d44bfe1e2becf6543 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 13 Jun 2017 11:35:04 +1200 Subject: [PATCH 9/9] Update RLS again --- src/tools/rls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rls b/src/tools/rls index bfe80cfa8db75..0d0f3baad02d6 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit bfe80cfa8db75500e67ca8762465d27662674637 +Subproject commit 0d0f3baad02d65d96befbb90e77bf8a326dd14f5