From d7f8ce834c5090627c394c9d6f2b86917b944a1c Mon Sep 17 00:00:00 2001 From: Mingwei Samuel Date: Fri, 30 Jun 2023 10:57:02 -0700 Subject: [PATCH] Re-add updated Span::start()/end()/line()/column() span-locations methods Updated for https://github.com/rust-lang/rust/pull/111571 --- .gitignore | 1 + Cargo.toml | 2 +- src/fallback.rs | 51 ++++++++++++++++++++++++++++--------------------- src/lib.rs | 39 ++++++++++++++++++++++++++----------- src/location.rs | 29 ---------------------------- src/wrapper.rs | 32 ++++++++++++++++++++++--------- tests/marker.rs | 7 ++----- tests/test.rs | 32 +++++++++++++++---------------- 8 files changed, 100 insertions(+), 93 deletions(-) delete mode 100644 src/location.rs diff --git a/.gitignore b/.gitignore index 69369904..4fb5d9e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /target **/*.rs.bk Cargo.lock +/.vscode diff --git a/Cargo.toml b/Cargo.toml index 33d92d37..1714ad2e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ rustversion = "1" proc-macro = [] default = ["proc-macro"] -# Expose methods Span::start and Span::end which give the line/column location +# Expose the old Span::start and Span::end methods which give the line/column location # of a token. span-locations = [] diff --git a/src/fallback.rs b/src/fallback.rs index 1b8b1257..f0fa740e 100644 --- a/src/fallback.rs +++ b/src/fallback.rs @@ -1,5 +1,3 @@ -#[cfg(span_locations)] -use crate::location::LineColumn; use crate::parse::{self, Cursor}; use crate::rcvec::{RcVec, RcVecBuilder, RcVecIntoIter, RcVecMut}; use crate::{Delimiter, Spacing, TokenTree}; @@ -357,21 +355,16 @@ struct FileInfo { #[cfg(all(span_locations, not(fuzzing)))] impl FileInfo { - fn offset_line_column(&self, offset: usize) -> LineColumn { + /// Returns `(line, column)`. + fn offset_line_column(&self, offset: usize) -> (usize, usize) { assert!(self.span_within(Span { lo: offset as u32, hi: offset as u32 })); let offset = offset - self.span.lo as usize; match self.lines.binary_search(&offset) { - Ok(found) => LineColumn { - line: found + 1, - column: 0, - }, - Err(idx) => LineColumn { - line: idx, - column: offset - self.lines[idx - 1], - }, + Ok(found) => (found + 1, 0), + Err(idx) => (idx, offset - self.lines[idx - 1]), } } @@ -516,9 +509,26 @@ impl Span { } #[cfg(span_locations)] - pub fn start(&self) -> LineColumn { + pub fn start(&self) -> Self { + Self { + lo: self.lo, + hi: self.lo, + } + } + + #[cfg(span_locations)] + pub fn end(&self) -> Self { + Self { + lo: self.hi, + hi: self.hi, + } + } + + /// Helper: returns `(line, column)`. + #[cfg(span_locations)] + fn line_column(&self) -> (usize, usize) { #[cfg(fuzzing)] - return LineColumn { line: 0, column: 0 }; + return (0, 0); #[cfg(not(fuzzing))] SOURCE_MAP.with(|cm| { @@ -529,16 +539,13 @@ impl Span { } #[cfg(span_locations)] - pub fn end(&self) -> LineColumn { - #[cfg(fuzzing)] - return LineColumn { line: 0, column: 0 }; + pub fn line(&self) -> usize { + self.line_column().0 + } - #[cfg(not(fuzzing))] - SOURCE_MAP.with(|cm| { - let cm = cm.borrow(); - let fi = cm.fileinfo(*self); - fi.offset_line_column(self.hi as usize) - }) + #[cfg(span_locations)] + pub fn column(&self) -> usize { + self.line_column().1 } #[cfg(not(span_locations))] diff --git a/src/lib.rs b/src/lib.rs index 11d1ede2..f609a322 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -142,8 +142,6 @@ mod imp; #[cfg(span_locations)] mod convert; -#[cfg(span_locations)] -mod location; use crate::extra::DelimSpan; use crate::marker::Marker; @@ -157,9 +155,6 @@ use std::error::Error; #[cfg(procmacro2_semver_exempt)] use std::path::PathBuf; -#[cfg(span_locations)] -pub use crate::location::LineColumn; - /// An abstract stream of tokens, or more concretely a sequence of token trees. /// /// This type provides interfaces for iterating over token trees and for @@ -461,7 +456,27 @@ impl Span { SourceFile::_new(self.inner.source_file()) } - /// Get the starting line/column in the source file for this span. + /// Creates an empty span pointing to directly before this span. + /// + /// This method requires the `"span-locations"` feature to be enabled. + #[cfg(span_locations)] + #[cfg_attr(doc_cfg, doc(cfg(feature = "span-locations")))] + pub fn start(&self) -> Self { + Self::_new(self.inner.start()) + } + + /// Creates an empty span pointing to directly after this span. + /// + /// This method requires the `"span-locations"` feature to be enabled. + #[cfg(span_locations)] + #[cfg_attr(doc_cfg, doc(cfg(feature = "span-locations")))] + pub fn end(&self) -> Self { + Self::_new(self.inner.end()) + } + + /// The one-indexed line of the source file where the span starts. + /// + /// To obtain the line of the span's end, use `span.end().line()`. /// /// This method requires the `"span-locations"` feature to be enabled. /// @@ -472,11 +487,13 @@ impl Span { /// line/column are always meaningful regardless of toolchain. #[cfg(span_locations)] #[cfg_attr(doc_cfg, doc(cfg(feature = "span-locations")))] - pub fn start(&self) -> LineColumn { - self.inner.start() + pub fn line(&self) -> usize { + self.inner.line() } - /// Get the ending line/column in the source file for this span. + /// The one-indexed column of the source file where the span starts. + /// + /// To obtain the column of the span's end, use `span.end().column()`. /// /// This method requires the `"span-locations"` feature to be enabled. /// @@ -487,8 +504,8 @@ impl Span { /// line/column are always meaningful regardless of toolchain. #[cfg(span_locations)] #[cfg_attr(doc_cfg, doc(cfg(feature = "span-locations")))] - pub fn end(&self) -> LineColumn { - self.inner.end() + pub fn column(&self) -> usize { + self.inner.column() } /// Create a new span encompassing `self` and `other`. diff --git a/src/location.rs b/src/location.rs deleted file mode 100644 index 463026c2..00000000 --- a/src/location.rs +++ /dev/null @@ -1,29 +0,0 @@ -use core::cmp::Ordering; - -/// A line-column pair representing the start or end of a `Span`. -/// -/// This type is semver exempt and not exposed by default. -#[cfg_attr(doc_cfg, doc(cfg(feature = "span-locations")))] -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub struct LineColumn { - /// The 1-indexed line in the source file on which the span starts or ends - /// (inclusive). - pub line: usize, - /// The 0-indexed column (in UTF-8 characters) in the source file on which - /// the span starts or ends (inclusive). - pub column: usize, -} - -impl Ord for LineColumn { - fn cmp(&self, other: &Self) -> Ordering { - self.line - .cmp(&other.line) - .then(self.column.cmp(&other.column)) - } -} - -impl PartialOrd for LineColumn { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} diff --git a/src/wrapper.rs b/src/wrapper.rs index c422e4f0..b5089520 100644 --- a/src/wrapper.rs +++ b/src/wrapper.rs @@ -1,6 +1,4 @@ use crate::detection::inside_proc_macro; -#[cfg(span_locations)] -use crate::location::LineColumn; use crate::{fallback, Delimiter, Punct, Spacing, TokenTree}; use core::fmt::{self, Debug, Display}; use core::iter::FromIterator; @@ -468,22 +466,38 @@ impl Span { } #[cfg(span_locations)] - pub fn start(&self) -> LineColumn { + pub fn start(&self) -> Self { match self { - Span::Compiler(_) => LineColumn { line: 0, column: 0 }, - Span::Fallback(s) => s.start(), + Self::Compiler(s) => Self::Compiler(s.start()), + Self::Fallback(s) => Self::Fallback(s.start()), } } #[cfg(span_locations)] - pub fn end(&self) -> LineColumn { + pub fn end(&self) -> Self { match self { - Span::Compiler(_) => LineColumn { line: 0, column: 0 }, - Span::Fallback(s) => s.end(), + Self::Compiler(s) => Self::Compiler(s.end()), + Self::Fallback(s) => Self::Fallback(s.end()), } } - pub fn join(&self, other: Span) -> Option { + #[cfg(span_locations)] + pub fn line(&self) -> usize { + match self { + Self::Compiler(s) => s.line(), + Self::Fallback(s) => s.line(), + } + } + + #[cfg(span_locations)] + pub fn column(&self) -> usize { + match self { + Self::Compiler(s) => s.column(), + Self::Fallback(s) => s.column(), + } + } + + pub fn join(&self, other: Self) -> Option { let ret = match (self, other) { #[cfg(proc_macro_span)] (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.join(b)?), diff --git a/tests/marker.rs b/tests/marker.rs index 5b45733b..97def4a4 100644 --- a/tests/marker.rs +++ b/tests/marker.rs @@ -55,9 +55,7 @@ assert_impl!(TokenTree is not Send or Sync); #[cfg(procmacro2_semver_exempt)] mod semver_exempt { - use proc_macro2::{LineColumn, SourceFile}; - - assert_impl!(LineColumn is Send and Sync); + use proc_macro2::SourceFile; assert_impl!(SourceFile is not Send or Sync); } @@ -68,7 +66,7 @@ mod unwind_safe { Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree, }; #[cfg(procmacro2_semver_exempt)] - use proc_macro2::{LineColumn, SourceFile}; + use proc_macro2::SourceFile; use std::panic::{RefUnwindSafe, UnwindSafe}; macro_rules! assert_unwind_safe { @@ -94,7 +92,6 @@ mod unwind_safe { #[cfg(procmacro2_semver_exempt)] assert_unwind_safe! { - LineColumn SourceFile } } diff --git a/tests/test.rs b/tests/test.rs index eb17f50a..68527ea5 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -331,10 +331,10 @@ fn literal_span() { #[cfg(span_locations)] { - assert_eq!(positive.span().start().column, 0); - assert_eq!(positive.span().end().column, 3); - assert_eq!(negative.span().start().column, 0); - assert_eq!(negative.span().end().column, 4); + assert_eq!(positive.span().start().column(), 0); + assert_eq!(positive.span().end().column(), 3); + assert_eq!(negative.span().start().column(), 0); + assert_eq!(negative.span().end().column(), 4); assert_eq!(subspan.unwrap().source_text().unwrap(), "."); } @@ -432,11 +432,11 @@ testing 123 #[test] fn default_span() { let start = Span::call_site().start(); - assert_eq!(start.line, 1); - assert_eq!(start.column, 0); + assert_eq!(start.line(), 1); + assert_eq!(start.column(), 0); let end = Span::call_site().end(); - assert_eq!(end.line, 1); - assert_eq!(end.column, 0); + assert_eq!(end.line(), 1); + assert_eq!(end.column(), 0); let source_file = Span::call_site().source_file(); assert_eq!(source_file.path().to_string_lossy(), ""); assert!(!source_file.is_real()); @@ -469,10 +469,10 @@ fn span_join() { let start = joined1.unwrap().start(); let end = joined1.unwrap().end(); - assert_eq!(start.line, 1); - assert_eq!(start.column, 0); - assert_eq!(end.line, 2); - assert_eq!(end.column, 3); + assert_eq!(start.line(), 1); + assert_eq!(start.column(), 0); + assert_eq!(end.line(), 2); + assert_eq!(end.column(), 3); assert_eq!( joined1.unwrap().source_file(), @@ -717,12 +717,12 @@ fn check_spans_internal(ts: TokenStream, lines: &mut &[(usize, usize, usize, usi *lines = rest; let start = i.span().start(); - assert_eq!(start.line, sline, "sline did not match for {}", i); - assert_eq!(start.column, scol, "scol did not match for {}", i); + assert_eq!(start.line(), sline, "sline did not match for {}", i); + assert_eq!(start.column(), scol, "scol did not match for {}", i); let end = i.span().end(); - assert_eq!(end.line, eline, "eline did not match for {}", i); - assert_eq!(end.column, ecol, "ecol did not match for {}", i); + assert_eq!(end.line(), eline, "eline did not match for {}", i); + assert_eq!(end.column(), ecol, "ecol did not match for {}", i); if let TokenTree::Group(g) = i { check_spans_internal(g.stream().clone(), lines);