@@ -16,7 +16,7 @@ use rustc_span::{
16
16
} ;
17
17
use std:: borrow:: Cow ;
18
18
use std:: fmt;
19
- use std:: ops:: Range ;
19
+ use std:: ops:: { Deref , Range } ;
20
20
21
21
pub trait HasSession {
22
22
fn sess ( & self ) -> & Session ;
@@ -94,10 +94,16 @@ impl IntoSpan for Range<BytePos> {
94
94
}
95
95
96
96
pub trait SpanRangeExt : SpanRange {
97
+ /// Attempts to get a handle to the source text. Returns `None` if either the span is malformed,
98
+ /// or the source text is not accessible.
99
+ fn get_source_text ( self , cx : & impl HasSession ) -> Option < SourceText > {
100
+ get_source_range ( cx. sess ( ) . source_map ( ) , self . into_range ( ) ) . and_then ( SourceText :: new)
101
+ }
102
+
97
103
/// Gets the source file, and range in the file, of the given span. Returns `None` if the span
98
104
/// extends through multiple files, or is malformed.
99
- fn get_source_text ( self , cx : & impl HasSession ) -> Option < SourceFileRange > {
100
- get_source_text ( cx. sess ( ) . source_map ( ) , self . into_range ( ) )
105
+ fn get_source_range ( self , cx : & impl HasSession ) -> Option < SourceFileRange > {
106
+ get_source_range ( cx. sess ( ) . source_map ( ) , self . into_range ( ) )
101
107
}
102
108
103
109
/// Calls the given function with the source text referenced and returns the value. Returns
@@ -144,21 +150,49 @@ pub trait SpanRangeExt: SpanRange {
144
150
fn trim_start ( self , cx : & impl HasSession ) -> Range < BytePos > {
145
151
trim_start ( cx. sess ( ) . source_map ( ) , self . into_range ( ) )
146
152
}
153
+ }
154
+ impl < T : SpanRange > SpanRangeExt for T { }
147
155
148
- /// Writes the referenced source text to the given writer. Will return `Err` if the source text
149
- /// could not be retrieved.
150
- fn write_source_text_to ( self , cx : & impl HasSession , dst : & mut impl fmt:: Write ) -> fmt:: Result {
151
- write_source_text_to ( cx. sess ( ) . source_map ( ) , self . into_range ( ) , dst)
156
+ /// Handle to a range of text in a source file.
157
+ pub struct SourceText ( SourceFileRange ) ;
158
+ impl SourceText {
159
+ /// Takes ownership of the source file handle if the source text is accessible.
160
+ pub fn new ( text : SourceFileRange ) -> Option < Self > {
161
+ if text. as_str ( ) . is_some ( ) {
162
+ Some ( Self ( text) )
163
+ } else {
164
+ None
165
+ }
166
+ }
167
+
168
+ /// Gets the source text.
169
+ pub fn as_str ( & self ) -> & str {
170
+ self . 0 . as_str ( ) . unwrap ( )
152
171
}
153
172
154
- /// Extracts the referenced source text as an owned string.
155
- fn source_text_to_string ( self , cx : & impl HasSession ) -> Option < String > {
156
- self . with_source_text ( cx, ToOwned :: to_owned)
173
+ /// Converts this into an owned string.
174
+ pub fn to_owned ( & self ) -> String {
175
+ self . as_str ( ) . to_owned ( )
176
+ }
177
+ }
178
+ impl Deref for SourceText {
179
+ type Target = str ;
180
+ fn deref ( & self ) -> & Self :: Target {
181
+ self . as_str ( )
182
+ }
183
+ }
184
+ impl AsRef < str > for SourceText {
185
+ fn as_ref ( & self ) -> & str {
186
+ self . as_str ( )
187
+ }
188
+ }
189
+ impl fmt:: Display for SourceText {
190
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
191
+ self . as_str ( ) . fmt ( f)
157
192
}
158
193
}
159
- impl < T : SpanRange > SpanRangeExt for T { }
160
194
161
- fn get_source_text ( sm : & SourceMap , sp : Range < BytePos > ) -> Option < SourceFileRange > {
195
+ fn get_source_range ( sm : & SourceMap , sp : Range < BytePos > ) -> Option < SourceFileRange > {
162
196
let start = sm. lookup_byte_offset ( sp. start ) ;
163
197
let end = sm. lookup_byte_offset ( sp. end ) ;
164
198
if !Lrc :: ptr_eq ( & start. sf , & end. sf ) || start. pos > end. pos {
@@ -169,7 +203,7 @@ fn get_source_text(sm: &SourceMap, sp: Range<BytePos>) -> Option<SourceFileRange
169
203
}
170
204
171
205
fn with_source_text < T > ( sm : & SourceMap , sp : Range < BytePos > , f : impl for < ' a > FnOnce ( & ' a str ) -> T ) -> Option < T > {
172
- if let Some ( src) = get_source_text ( sm, sp)
206
+ if let Some ( src) = get_source_range ( sm, sp)
173
207
&& let Some ( src) = src. as_str ( )
174
208
{
175
209
Some ( f ( src) )
@@ -183,7 +217,7 @@ fn with_source_text_and_range<T>(
183
217
sp : Range < BytePos > ,
184
218
f : impl for < ' a > FnOnce ( & ' a str , Range < usize > ) -> T ,
185
219
) -> Option < T > {
186
- if let Some ( src) = get_source_text ( sm, sp)
220
+ if let Some ( src) = get_source_range ( sm, sp)
187
221
&& let Some ( text) = & src. sf . src
188
222
{
189
223
Some ( f ( text, src. range ) )
@@ -198,7 +232,7 @@ fn map_range(
198
232
sp : Range < BytePos > ,
199
233
f : impl for < ' a > FnOnce ( & ' a str , Range < usize > ) -> Option < Range < usize > > ,
200
234
) -> Option < Range < BytePos > > {
201
- if let Some ( src) = get_source_text ( sm, sp. clone ( ) )
235
+ if let Some ( src) = get_source_range ( sm, sp. clone ( ) )
202
236
&& let Some ( text) = & src. sf . src
203
237
&& let Some ( range) = f ( text, src. range . clone ( ) )
204
238
{
@@ -232,13 +266,6 @@ fn trim_start(sm: &SourceMap, sp: Range<BytePos>) -> Range<BytePos> {
232
266
. unwrap_or ( sp)
233
267
}
234
268
235
- fn write_source_text_to ( sm : & SourceMap , sp : Range < BytePos > , dst : & mut impl fmt:: Write ) -> fmt:: Result {
236
- match with_source_text ( sm, sp, |src| dst. write_str ( src) ) {
237
- Some ( x) => x,
238
- None => Err ( fmt:: Error ) ,
239
- }
240
- }
241
-
242
269
pub struct SourceFileRange {
243
270
pub sf : Lrc < SourceFile > ,
244
271
pub range : Range < usize > ,
0 commit comments