From 7dbae7b3400e72c5cd83858550a9ae2cef37d64f 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 + src/fallback.rs | 57 +++++++++++++++++++++++++++---------------------- src/lib.rs | 41 ++++++++++++++++++++++++----------- src/location.rs | 29 ------------------------- src/wrapper.rs | 32 +++++++++++++++++++-------- tests/marker.rs | 9 +++----- tests/test.rs | 32 +++++++++++++-------------- 7 files changed, 103 insertions(+), 98 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/src/fallback.rs b/src/fallback.rs index 7839d4e8..25d49c2d 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}; @@ -356,21 +354,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]), } } @@ -573,29 +566,43 @@ 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(|sm| { - let sm = sm.borrow(); - let fi = sm.fileinfo(*self); + SOURCE_MAP.with(|cm| { + let cm = cm.borrow(); + let fi = cm.fileinfo(*self); fi.offset_line_column(self.lo as usize) }) } #[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(|sm| { - let sm = sm.borrow(); - let fi = sm.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 1bb24612..dd09d394 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -157,9 +157,6 @@ use crate::fallback as imp; #[cfg(wrap_proc_macro)] mod imp; -#[cfg(span_locations)] -mod location; - use crate::extra::DelimSpan; use crate::marker::{ProcMacroAutoTraits, MARKER}; use core::cmp::Ordering; @@ -173,10 +170,6 @@ use std::error::Error; #[cfg(procmacro2_semver_exempt)] use std::path::PathBuf; -#[cfg(span_locations)] -#[cfg_attr(doc_cfg, doc(cfg(feature = "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 @@ -490,7 +483,27 @@ impl Span { self.inner.byte_range() } - /// 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. /// @@ -501,11 +514,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. /// @@ -516,8 +531,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 a71043ab..adcfd334 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}; #[cfg(span_locations)] @@ -474,22 +472,38 @@ impl Span { } #[cfg(span_locations)] - pub fn start(&self) -> LineColumn { + pub fn start(&self) -> Self { + match self { + Self::Compiler(s) => Self::Compiler(s.start()), + Self::Fallback(s) => Self::Fallback(s.start()), + } + } + + #[cfg(span_locations)] + pub fn end(&self) -> Self { + match self { + Self::Compiler(s) => Self::Compiler(s.end()), + Self::Fallback(s) => Self::Fallback(s.end()), + } + } + + #[cfg(span_locations)] + pub fn line(&self) -> usize { match self { - Span::Compiler(_) => LineColumn { line: 0, column: 0 }, - Span::Fallback(s) => s.start(), + Self::Compiler(s) => s.line(), + Self::Fallback(s) => s.line(), } } #[cfg(span_locations)] - pub fn end(&self) -> LineColumn { + pub fn column(&self) -> usize { match self { - Span::Compiler(_) => LineColumn { line: 0, column: 0 }, - Span::Fallback(s) => s.end(), + Self::Compiler(s) => s.column(), + Self::Fallback(s) => s.column(), } } - pub fn join(&self, other: Span) -> Option { + 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 99f64c06..a814c96b 100644 --- a/tests/marker.rs +++ b/tests/marker.rs @@ -56,19 +56,17 @@ 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); } mod unwind_safe { + #[cfg(procmacro2_semver_exempt)] + use proc_macro2::SourceFile; use proc_macro2::{ Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree, }; - #[cfg(procmacro2_semver_exempt)] - use proc_macro2::{LineColumn, 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 486955cf..da1f7be9 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -315,10 +315,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(), "."); } @@ -434,11 +434,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()); @@ -471,10 +471,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(), @@ -719,12 +719,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);