Skip to content

Commit 1566040

Browse files
committed
refactor: Use Origin for Snippet::origin
1 parent a81dc31 commit 1566040

File tree

2 files changed

+95
-52
lines changed

2 files changed

+95
-52
lines changed

src/renderer/mod.rs

Lines changed: 66 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -239,14 +239,14 @@ impl Renderer {
239239
group.elements.iter().find_map(|s| match &s {
240240
Element::Cause(cause) => {
241241
if cause.markers.iter().any(|m| m.kind.is_primary()) {
242-
Some(cause.origin)
242+
Some(cause.origin.as_ref())
243243
} else {
244244
None
245245
}
246246
}
247247
Element::Origin(origin) => {
248248
if origin.primary {
249-
Some(Some(origin.origin))
249+
Some(Some(origin))
250250
} else {
251251
None
252252
}
@@ -260,30 +260,30 @@ impl Renderer {
260260
.iter()
261261
.find_map(|group| {
262262
group.elements.iter().find_map(|s| match &s {
263-
Element::Cause(cause) => Some(cause.origin),
264-
Element::Origin(origin) => Some(Some(origin.origin)),
263+
Element::Cause(cause) => Some(cause.origin.as_ref()),
264+
Element::Origin(origin) => Some(Some(origin)),
265265
_ => None,
266266
})
267267
})
268268
.unwrap_or_default(),
269269
);
270270
let group_len = message.groups.len();
271-
for (g, group) in message.groups.into_iter().enumerate() {
271+
for (g, group) in message.groups.iter().enumerate() {
272272
let mut buffer = StyledBuffer::new();
273273
let primary_origin = group
274274
.elements
275275
.iter()
276276
.find_map(|s| match &s {
277277
Element::Cause(cause) => {
278278
if cause.markers.iter().any(|m| m.kind.is_primary()) {
279-
Some(cause.origin)
279+
Some(cause.origin.as_ref())
280280
} else {
281281
None
282282
}
283283
}
284284
Element::Origin(origin) => {
285285
if origin.primary {
286-
Some(Some(origin.origin))
286+
Some(Some(origin))
287287
} else {
288288
None
289289
}
@@ -295,8 +295,8 @@ impl Renderer {
295295
.elements
296296
.iter()
297297
.find_map(|s| match &s {
298-
Element::Cause(cause) => Some(cause.origin),
299-
Element::Origin(origin) => Some(Some(origin.origin)),
298+
Element::Cause(cause) => Some(cause.origin.as_ref()),
299+
Element::Origin(origin) => Some(Some(origin)),
300300
_ => None,
301301
})
302302
.unwrap_or_default(),
@@ -490,26 +490,27 @@ impl Renderer {
490490
labels = Some(labels_inner);
491491
}
492492

493-
if let Some(origin) = cause.origin {
494-
let mut origin = Origin::new(origin);
493+
if let Some(mut origin) = cause.origin.clone() {
495494
origin.primary = true;
496495

497-
let source_map = SourceMap::new(cause.source, cause.line_start);
498-
let (_depth, annotated_lines) =
499-
source_map.annotated_lines(cause.markers.clone(), cause.fold);
496+
if origin.line.is_none() || origin.char_column.is_none() {
497+
let source_map = SourceMap::new(cause.source, cause.line_start);
498+
let (_depth, annotated_lines) =
499+
source_map.annotated_lines(cause.markers.clone(), cause.fold);
500500

501-
if let Some(primary_line) = annotated_lines
502-
.iter()
503-
.find(|l| l.annotations.iter().any(LineAnnotation::is_primary))
504-
.or(annotated_lines.iter().find(|l| !l.annotations.is_empty()))
505-
{
506-
origin.line = Some(primary_line.line_index);
507-
if let Some(first_annotation) = primary_line
508-
.annotations
501+
if let Some(primary_line) = annotated_lines
509502
.iter()
510-
.min_by_key(|a| (Reverse(a.is_primary()), a.start.char))
503+
.find(|l| l.annotations.iter().any(LineAnnotation::is_primary))
504+
.or(annotated_lines.iter().find(|l| !l.annotations.is_empty()))
511505
{
512-
origin.char_column = Some(first_annotation.start.char + 1);
506+
origin.line = Some(primary_line.line_index);
507+
if let Some(first_annotation) = primary_line
508+
.annotations
509+
.iter()
510+
.min_by_key(|a| (Reverse(a.is_primary()), a.start.char))
511+
{
512+
origin.char_column = Some(first_annotation.start.char + 1);
513+
}
513514
}
514515
}
515516

@@ -784,32 +785,40 @@ impl Renderer {
784785
buffer: &mut StyledBuffer,
785786
max_line_num_len: usize,
786787
snippet: &Snippet<'_, Annotation<'_>>,
787-
primary_origin: Option<&str>,
788+
primary_origin: Option<&Origin<'_>>,
788789
sm: &SourceMap<'_>,
789790
annotated_lines: &[AnnotatedLineInfo<'_>],
790791
multiline_depth: usize,
791792
is_cont: bool,
792793
) {
793-
if let Some(origin) = snippet.origin {
794-
let mut origin = Origin::new(origin);
794+
if let Some(mut origin) = snippet.origin.clone() {
795795
// print out the span location and spacer before we print the annotated source
796796
// to do this, we need to know if this span will be primary
797-
let is_primary = primary_origin == Some(origin.origin);
797+
let is_primary = origin.primary || primary_origin == Some(&origin);
798798

799799
if is_primary {
800800
origin.primary = true;
801-
if let Some(primary_line) = annotated_lines
802-
.iter()
803-
.find(|l| l.annotations.iter().any(LineAnnotation::is_primary))
804-
.or(annotated_lines.iter().find(|l| !l.annotations.is_empty()))
805-
{
806-
origin.line = Some(primary_line.line_index);
807-
if let Some(first_annotation) = primary_line
808-
.annotations
801+
802+
if origin.line.is_none() || origin.char_column.is_none() {
803+
if let Some(primary_line) = annotated_lines
809804
.iter()
810-
.min_by_key(|a| (Reverse(a.is_primary()), a.start.char))
805+
.find(|l| l.annotations.iter().any(LineAnnotation::is_primary))
806+
.or(annotated_lines.iter().find(|l| !l.annotations.is_empty()))
811807
{
812-
origin.char_column = Some(first_annotation.start.char + 1);
808+
if origin.line.is_none() {
809+
origin.line = Some(primary_line.line_index);
810+
}
811+
812+
// Always set the char column, as it is either `None`
813+
// or we set the line and now need to set the column on
814+
// that line.
815+
if let Some(first_annotation) = primary_line
816+
.annotations
817+
.iter()
818+
.min_by_key(|a| (Reverse(a.is_primary()), a.start.char))
819+
{
820+
origin.char_column = Some(first_annotation.start.char + 1);
821+
}
813822
}
814823
}
815824
} else {
@@ -829,10 +838,12 @@ impl Renderer {
829838
buffer_msg_line_offset,
830839
max_line_num_len + 1,
831840
);
832-
if let Some(first_line) = annotated_lines.first() {
833-
origin.line = Some(first_line.line_index);
834-
if let Some(first_annotation) = first_line.annotations.first() {
835-
origin.char_column = Some(first_annotation.start.char + 1);
841+
if origin.line.is_none() {
842+
if let Some(first_line) = annotated_lines.first() {
843+
origin.line = Some(first_line.line_index);
844+
if let Some(first_annotation) = first_line.annotations.first() {
845+
origin.char_column = Some(first_annotation.start.char + 1);
846+
}
836847
}
837848
}
838849
}
@@ -1648,7 +1659,7 @@ impl Renderer {
16481659
suggestion: &Snippet<'_, Patch<'_>>,
16491660
max_line_num_len: usize,
16501661
sm: &SourceMap<'_>,
1651-
primary_origin: Option<&str>,
1662+
primary_origin: Option<&Origin<'_>>,
16521663
is_cont: bool,
16531664
) {
16541665
let suggestions = sm.splice_lines(suggestion.markers.clone());
@@ -1671,14 +1682,22 @@ impl Renderer {
16711682
ElementStyle::LineNumber,
16721683
);
16731684
}
1674-
if suggestion.origin != primary_origin {
1675-
if let Some(origin) = suggestion.origin {
1676-
let (loc, _) = sm.span_to_locations(parts[0].span.clone());
1685+
1686+
if suggestion.origin.as_ref() != primary_origin && primary_origin.is_some() {
1687+
if let Some(origin) = suggestion.origin.clone() {
1688+
let (line, char_col) =
1689+
if let (Some(line), Some(char_col)) = (origin.line, origin.char_column) {
1690+
(line, char_col)
1691+
} else {
1692+
let (loc, _) = sm.span_to_locations(parts[0].span.clone());
1693+
(loc.line, loc.char + 1)
1694+
};
1695+
16771696
// --> file.rs:line:col
16781697
// |
16791698
let arrow = self.file_start();
16801699
buffer.puts(row_num - 1, 0, arrow, ElementStyle::LineNumber);
1681-
let message = format!("{}:{}:{}", origin, loc.line, loc.char + 1);
1700+
let message = format!("{}:{}:{}", origin.origin, line, char_col);
16821701
if is_cont {
16831702
buffer.append(row_num - 1, &message, ElementStyle::LineAndColumn);
16841703
} else {

src/snippet.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ pub struct Title<'a> {
164164
/// A source view [`Element`] in a [`Group`]
165165
#[derive(Clone, Debug)]
166166
pub struct Snippet<'a, T> {
167-
pub(crate) origin: Option<&'a str>,
167+
pub(crate) origin: Option<Origin<'a>>,
168168
pub(crate) line_start: usize,
169169
pub(crate) source: &'a str,
170170
pub(crate) markers: Vec<T>,
@@ -200,15 +200,19 @@ impl<'a, T: Clone> Snippet<'a, T> {
200200

201201
/// The location of the [`source`][Self::source] (e.g. a path)
202202
///
203+
/// If just a location is passed (i.e. a string) in the line and column
204+
/// numbers are automatically inferred. If you want to explicitly set the
205+
/// line and column you can create an [`Origin`] and pass it in.
206+
///
203207
/// <div class="warning">
204208
///
205209
/// Text passed to this function is considered "untrusted input", as such
206210
/// all text is passed through a normalization function. Pre-styled text is
207211
/// not allowed to be passed to this function.
208212
///
209213
/// </div>
210-
pub fn origin(mut self, origin: &'a str) -> Self {
211-
self.origin = Some(origin);
214+
pub fn origin(mut self, origin: impl Into<Origin<'a>>) -> Self {
215+
self.origin = Some(origin.into());
212216
self
213217
}
214218

@@ -375,8 +379,16 @@ impl<'a> Patch<'a> {
375379
}
376380
}
377381

378-
/// The location of the [`Snippet`] (e.g. a path)
379-
#[derive(Clone, Debug)]
382+
/// The location of the [`Snippet`] (e.g. a path).
383+
///
384+
/// This should be used if you want to display the file details by
385+
/// itself, or you want to set the line number and column explicitly.
386+
/// Otherwise, it is better to use [`Snippet::origin`].
387+
///
388+
/// Note: `line` is always respected if set, but `char_column` is only
389+
/// respected if `line` has been set. `primary` is respected unless the origin
390+
/// is the first one in a [`Group`], in which case it is ignored.
391+
#[derive(Clone, Debug, Eq, PartialEq)]
380392
pub struct Origin<'a> {
381393
pub(crate) origin: &'a str,
382394
pub(crate) line: Option<usize>,
@@ -423,6 +435,18 @@ impl<'a> Origin<'a> {
423435
}
424436
}
425437

438+
impl<'a> From<&'a str> for Origin<'a> {
439+
fn from(origin: &'a str) -> Self {
440+
Self::new(origin)
441+
}
442+
}
443+
444+
impl<'a> From<&'a String> for Origin<'a> {
445+
fn from(origin: &'a String) -> Self {
446+
Self::new(origin)
447+
}
448+
}
449+
426450
fn newline_count(body: &str) -> usize {
427451
#[cfg(feature = "simd")]
428452
{

0 commit comments

Comments
 (0)