From 099f96472fb89dd03c8c01f5a9b68b7e5e25a23c Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 6 Nov 2017 14:56:43 +1300 Subject: [PATCH 1/2] save-analysis: give better info for Unions --- src/librustc_save_analysis/dump_visitor.rs | 54 +++++++++++----------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 23f6e6b46ba..688d3c82810 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -521,39 +521,41 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { item: &'l ast::Item, def: &'l ast::VariantData, ty_params: &'l ast::Generics) { + debug!("process_struct {:?} {:?}", item, item.span); let name = item.ident.to_string(); let qualname = format!("::{}", self.tcx.node_path_str(item.id)); - let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Struct); - let (value, fields) = - if let ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) = item.node - { - let include_priv_fields = !self.save_ctxt.config.pub_only; - let fields_str = fields - .iter() - .enumerate() - .filter_map(|(i, f)| { - if include_priv_fields || f.vis == ast::Visibility::Public { - f.ident.map(|i| i.to_string()).or_else(|| Some(i.to_string())) - } else { - None - } - }) - .collect::>() - .join(", "); - let value = format!("{} {{ {} }}", name, fields_str); - (value, fields.iter().map(|f| ::id_from_node_id(f.id, &self.save_ctxt)).collect()) - } else { - (String::new(), vec![]) + let (kind, keyword) = match item.node { + ast::ItemKind::Struct(_, _) => (DefKind::Struct, keywords::Struct), + ast::ItemKind::Union(_, _) => (DefKind::Union, keywords::Union), + _ => unreachable!(), + }; + + let sub_span = self.span.sub_span_after_keyword(item.span, keyword); + let (value, fields) = match item.node { + ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) | + ast::ItemKind::Union(ast::VariantData::Struct(ref fields, _), _) => { + let include_priv_fields = !self.save_ctxt.config.pub_only; + let fields_str = fields + .iter() + .enumerate() + .filter_map(|(i, f)| { + if include_priv_fields || f.vis == ast::Visibility::Public { + f.ident.map(|i| i.to_string()).or_else(|| Some(i.to_string())) + } else { + None + } + }) + .collect::>() + .join(", "); + let value = format!("{} {{ {} }}", name, fields_str); + (value, fields.iter().map(|f| ::id_from_node_id(f.id, &self.save_ctxt)).collect()) + } + _ => (String::new(), vec![]) }; if !self.span.filter_generated(sub_span, item.span) { let span = self.span_from_span(sub_span.expect("No span found for struct")); - let kind = match item.node { - ast::ItemKind::Struct(_, _) => DefKind::Struct, - ast::ItemKind::Union(_, _) => DefKind::Union, - _ => unreachable!(), - }; self.dumper.dump_def(item.vis == ast::Visibility::Public, Def { kind, id: ::id_from_node_id(item.id, &self.save_ctxt), From b709a7ebc53f9c61890590233ee4defc5b9b5c2c Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 6 Nov 2017 15:52:42 +1300 Subject: [PATCH 2/2] save-analysis: fix bugs in method chains Use the span we save in the PathSegment for a method call, rather than searching for it in the text. Fixes https://github.com/nrc/rls-analysis/issues/111 --- src/librustc_save_analysis/dump_visitor.rs | 1 + src/librustc_save_analysis/lib.rs | 33 +++++++++-------- src/librustc_save_analysis/span_utils.rs | 43 +--------------------- 3 files changed, 20 insertions(+), 57 deletions(-) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 688d3c82810..d190ae1431f 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -878,6 +878,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { ex: &'l ast::Expr, seg: &'l ast::PathSegment, args: &'l [P]) { + debug!("process_method_call {:?} {:?}", ex, ex.span); if let Some(mcd) = self.save_ctxt.get_expr_data(ex) { down_cast_data!(mcd, RefData, ex.span); if !generated_code(ex.span) { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 5ae1ba92262..edb51ae59e1 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -546,16 +546,16 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } } - ast::ExprKind::MethodCall(..) => { + ast::ExprKind::MethodCall(ref seg, ..) => { let expr_hir_id = self.tcx.hir.definitions().node_to_hir_id(expr.id); let method_id = self.tables.type_dependent_defs()[expr_hir_id].def_id(); let (def_id, decl_id) = match self.tcx.associated_item(method_id).container { ty::ImplContainer(_) => (Some(method_id), None), ty::TraitContainer(_) => (None, Some(method_id)), }; - let sub_span = self.span_utils.sub_span_for_meth_name(expr.span); - filter!(self.span_utils, sub_span, expr.span, None); - let span = self.span_from_span(sub_span.unwrap()); + let sub_span = seg.span; + filter!(self.span_utils, Some(sub_span), expr.span, None); + let span = self.span_from_span(sub_span); Some(Data::RefData(Ref { kind: RefKind::Function, span, @@ -627,13 +627,18 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { false } + if path.segments.is_empty() { + return None; + } + let def = self.get_path_def(id); - let sub_span = self.span_utils.span_for_last_ident(path.span); - filter!(self.span_utils, sub_span, path.span, None); + let last_seg = &path.segments[path.segments.len() - 1]; + let sub_span = last_seg.span; + filter!(self.span_utils, Some(sub_span), path.span, None); match def { HirDef::Upvar(id, ..) | HirDef::Local(id) => { - let span = self.span_from_span(sub_span.unwrap()); + let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Variable, span, @@ -644,7 +649,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { HirDef::Const(..) | HirDef::AssociatedConst(..) | HirDef::VariantCtor(..) => { - let span = self.span_from_span(sub_span.unwrap()); + let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Variable, span, @@ -670,7 +675,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { HirDef::AssociatedTy(def_id) | HirDef::Trait(def_id) | HirDef::TyParam(def_id) => { - let span = self.span_from_span(sub_span.unwrap()); + let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Type, span, @@ -681,7 +686,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { // This is a reference to a tuple struct where the def_id points // to an invisible constructor function. That is not a very useful // def, so adjust to point to the tuple struct itself. - let span = self.span_from_span(sub_span.unwrap()); + let span = self.span_from_span(sub_span); let parent_def_id = self.tcx.parent_def_id(def_id).unwrap(); Some(Ref { kind: RefKind::Type, @@ -690,8 +695,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { }) } HirDef::Method(decl_id) => { - let sub_span = self.span_utils.sub_span_for_meth_name(path.span); - filter!(self.span_utils, sub_span, path.span, None); let def_id = if decl_id.is_local() { let ti = self.tcx.associated_item(decl_id); self.tcx.associated_items(ti.container.id()) @@ -700,7 +703,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } else { None }; - let span = self.span_from_span(sub_span.unwrap()); + let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Function, span, @@ -708,7 +711,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { }) } HirDef::Fn(def_id) => { - let span = self.span_from_span(sub_span.unwrap()); + let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Function, span, @@ -716,7 +719,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { }) } HirDef::Mod(def_id) => { - let span = self.span_from_span(sub_span.unwrap()); + let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Mod, span, diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs index b9d82b8e251..5bfb4d1b3b2 100644 --- a/src/librustc_save_analysis/span_utils.rs +++ b/src/librustc_save_analysis/span_utils.rs @@ -103,47 +103,6 @@ impl<'a> SpanUtils<'a> { } } - // Return the span for the last ident before a `(` or `<` or '::<' and outside any - // any brackets, or the last span. - pub fn sub_span_for_meth_name(&self, span: Span) -> Option { - let mut toks = self.retokenise_span(span); - let mut prev = toks.real_token(); - let mut result = None; - let mut bracket_count = 0; - let mut prev_span = None; - while prev.tok != token::Eof { - prev_span = None; - let mut next = toks.real_token(); - - if (next.tok == token::OpenDelim(token::Paren) || next.tok == token::Lt) && - bracket_count == 0 && prev.tok.is_ident() { - result = Some(prev.sp); - } - - if bracket_count == 0 && next.tok == token::ModSep { - let old = prev; - prev = next; - next = toks.real_token(); - if next.tok == token::Lt && old.tok.is_ident() { - result = Some(old.sp); - } - } - - bracket_count += match prev.tok { - token::OpenDelim(token::Paren) | token::Lt => 1, - token::CloseDelim(token::Paren) | token::Gt => -1, - token::BinOp(token::Shr) => -2, - _ => 0, - }; - - if prev.tok.is_ident() && bracket_count == 0 { - prev_span = Some(prev.sp); - } - prev = next; - } - result.or(prev_span) - } - // Return the span for the last ident before a `<` and outside any // angle brackets, or the last span. pub fn sub_span_for_type_name(&self, span: Span) -> Option { @@ -330,7 +289,7 @@ impl<'a> SpanUtils<'a> { } macro_rules! filter { - ($util: expr, $span: ident, $parent: expr, None) => { + ($util: expr, $span: expr, $parent: expr, None) => { if $util.filter_generated($span, $parent) { return None; }