diff options
| author | Nick Cameron <ncameron@mozilla.com> | 2017-11-06 15:52:42 +1300 |
|---|---|---|
| committer | Nick Cameron <ncameron@mozilla.com> | 2017-11-06 15:52:42 +1300 |
| commit | b709a7ebc53f9c61890590233ee4defc5b9b5c2c (patch) | |
| tree | 7a7c9f28e4e4ded04d5cd7c82800a4a750090970 | |
| parent | 099f96472fb89dd03c8c01f5a9b68b7e5e25a23c (diff) | |
| download | rust-b709a7ebc53f9c61890590233ee4defc5b9b5c2c.tar.gz rust-b709a7ebc53f9c61890590233ee4defc5b9b5c2c.zip | |
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
| -rw-r--r-- | src/librustc_save_analysis/dump_visitor.rs | 1 | ||||
| -rw-r--r-- | src/librustc_save_analysis/lib.rs | 33 | ||||
| -rw-r--r-- | 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<ast::Expr>]) { + 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<Span> { - 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<Span> { @@ -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; } |
