diff options
Diffstat (limited to 'src/tools/rustfmt/src/spanned.rs')
-rw-r--r-- | src/tools/rustfmt/src/spanned.rs | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs new file mode 100644 index 000000000..2136cfeae --- /dev/null +++ b/src/tools/rustfmt/src/spanned.rs @@ -0,0 +1,199 @@ +use std::cmp::max; + +use rustc_ast::{ast, ptr}; +use rustc_span::{source_map, Span}; + +use crate::macros::MacroArg; +use crate::utils::{mk_sp, outer_attributes}; + +/// Spanned returns a span including attributes, if available. +pub(crate) trait Spanned { + fn span(&self) -> Span; +} + +impl<T: Spanned> Spanned for ptr::P<T> { + fn span(&self) -> Span { + (**self).span() + } +} + +impl<T> Spanned for source_map::Spanned<T> { + fn span(&self) -> Span { + self.span + } +} + +macro_rules! span_with_attrs_lo_hi { + ($this:ident, $lo:expr, $hi:expr) => {{ + let attrs = outer_attributes(&$this.attrs); + if attrs.is_empty() { + mk_sp($lo, $hi) + } else { + mk_sp(attrs[0].span.lo(), $hi) + } + }}; +} + +macro_rules! span_with_attrs { + ($this:ident) => { + span_with_attrs_lo_hi!($this, $this.span.lo(), $this.span.hi()) + }; +} + +macro_rules! implement_spanned { + ($this:ty) => { + impl Spanned for $this { + fn span(&self) -> Span { + span_with_attrs!(self) + } + } + }; +} + +// Implement `Spanned` for structs with `attrs` field. +implement_spanned!(ast::AssocItem); +implement_spanned!(ast::Expr); +implement_spanned!(ast::ExprField); +implement_spanned!(ast::ForeignItem); +implement_spanned!(ast::Item); +implement_spanned!(ast::Local); + +impl Spanned for ast::Stmt { + fn span(&self) -> Span { + match self.kind { + ast::StmtKind::Local(ref local) => mk_sp(local.span().lo(), self.span.hi()), + ast::StmtKind::Item(ref item) => mk_sp(item.span().lo(), self.span.hi()), + ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { + mk_sp(expr.span().lo(), self.span.hi()) + } + ast::StmtKind::MacCall(ref mac_stmt) => { + if mac_stmt.attrs.is_empty() { + self.span + } else { + mk_sp(mac_stmt.attrs[0].span.lo(), self.span.hi()) + } + } + ast::StmtKind::Empty => self.span, + } + } +} + +impl Spanned for ast::Pat { + fn span(&self) -> Span { + self.span + } +} + +impl Spanned for ast::Ty { + fn span(&self) -> Span { + self.span + } +} + +impl Spanned for ast::Arm { + fn span(&self) -> Span { + let lo = if self.attrs.is_empty() { + self.pat.span.lo() + } else { + self.attrs[0].span.lo() + }; + span_with_attrs_lo_hi!(self, lo, self.body.span.hi()) + } +} + +impl Spanned for ast::Param { + fn span(&self) -> Span { + if crate::items::is_named_param(self) { + mk_sp(crate::items::span_lo_for_param(self), self.ty.span.hi()) + } else { + self.ty.span + } + } +} + +impl Spanned for ast::GenericParam { + fn span(&self) -> Span { + let lo = match self.kind { + _ if !self.attrs.is_empty() => self.attrs[0].span.lo(), + ast::GenericParamKind::Const { kw_span, .. } => kw_span.lo(), + _ => self.ident.span.lo(), + }; + let hi = if self.bounds.is_empty() { + self.ident.span.hi() + } else { + self.bounds.last().unwrap().span().hi() + }; + let ty_hi = if let ast::GenericParamKind::Type { + default: Some(ref ty), + } + | ast::GenericParamKind::Const { ref ty, .. } = self.kind + { + ty.span().hi() + } else { + hi + }; + mk_sp(lo, max(hi, ty_hi)) + } +} + +impl Spanned for ast::FieldDef { + fn span(&self) -> Span { + span_with_attrs_lo_hi!(self, self.span.lo(), self.ty.span.hi()) + } +} + +impl Spanned for ast::WherePredicate { + fn span(&self) -> Span { + match *self { + ast::WherePredicate::BoundPredicate(ref p) => p.span, + ast::WherePredicate::RegionPredicate(ref p) => p.span, + ast::WherePredicate::EqPredicate(ref p) => p.span, + } + } +} + +impl Spanned for ast::FnRetTy { + fn span(&self) -> Span { + match *self { + ast::FnRetTy::Default(span) => span, + ast::FnRetTy::Ty(ref ty) => ty.span, + } + } +} + +impl Spanned for ast::GenericArg { + fn span(&self) -> Span { + match *self { + ast::GenericArg::Lifetime(ref lt) => lt.ident.span, + ast::GenericArg::Type(ref ty) => ty.span(), + ast::GenericArg::Const(ref _const) => _const.value.span(), + } + } +} + +impl Spanned for ast::GenericBound { + fn span(&self) -> Span { + match *self { + ast::GenericBound::Trait(ref ptr, _) => ptr.span, + ast::GenericBound::Outlives(ref l) => l.ident.span, + } + } +} + +impl Spanned for MacroArg { + fn span(&self) -> Span { + match *self { + MacroArg::Expr(ref expr) => expr.span(), + MacroArg::Ty(ref ty) => ty.span(), + MacroArg::Pat(ref pat) => pat.span(), + MacroArg::Item(ref item) => item.span(), + MacroArg::Keyword(_, span) => span, + } + } +} + +impl Spanned for ast::NestedMetaItem { + fn span(&self) -> Span { + self.span() + } +} |