Skip to content

Commit 1159e78

Browse files
committed
move locus calculation to separate function
1 parent 8d1762e commit 1159e78

4 files changed

Lines changed: 48 additions & 23 deletions

File tree

codespan-reporting/examples/custom_files.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ mod files {
7474
}
7575

7676
/// An opaque file identifier.
77-
#[derive(Copy, Clone, PartialEq, Eq)]
77+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
7878
pub struct FileId(u32);
7979

8080
#[derive(Debug, Clone)]

codespan-reporting/src/diagnostic.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
#[cfg(feature = "serialization")]
44
use serde::{Deserialize, Serialize};
5+
use std::collections::BTreeMap;
56
use std::ops::Range;
67
use std::string::ToString;
78

@@ -51,7 +52,7 @@ impl PartialOrd for Severity {
5152
}
5253
}
5354

54-
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)]
55+
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
5556
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
5657
pub enum LabelStyle {
5758
/// Labels that describe the primary cause of a diagnostic.
@@ -114,7 +115,9 @@ impl<FileId> Label<FileId> {
114115
/// Represents a diagnostic message that can provide information like errors and
115116
/// warnings to the user.
116117
///
117-
/// The position of a Diagnostic is considered to be the position of the [`Label`] that has the earliest starting position and has the highest style which appears in all the labels of the diagnostic.
118+
/// The position of a Diagnostic is considered to be the position of the
119+
/// [`Label`] that has the earliest starting position and has the highest style
120+
/// which appears in all the labels of the diagnostic.
118121
#[derive(Clone, Debug, PartialEq, Eq)]
119122
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
120123
pub struct Diagnostic<FileId> {
@@ -207,4 +210,36 @@ impl<FileId> Diagnostic<FileId> {
207210
self.notes.append(&mut notes);
208211
self
209212
}
213+
214+
/// Calculate the locus of this diagnostic.
215+
///
216+
/// If this Diagnostic covers multple files, a Vec with multiple values
217+
/// will be returned. Or contrary, if there are no labels in the
218+
/// Diagnostic, an empty Vec will be returned.
219+
pub fn locuses(&self) -> BTreeMap<FileId, usize>
220+
where
221+
FileId: Copy + Ord,
222+
{
223+
let mut labels = self
224+
.labels
225+
.iter()
226+
.map(|label| (label.file_id, label.style, label.range.start))
227+
.collect::<Vec<_>>();
228+
229+
labels.sort_unstable_by(|a, b| {
230+
a.0.partial_cmp(&b.0)
231+
.unwrap_or(std::cmp::Ordering::Equal)
232+
.then_with(|| a.1.cmp(&b.1))
233+
.then_with(|| a.2.cmp(&b.2))
234+
// reverse the sorting so we can use `Extend` to deduplicate
235+
.reverse()
236+
});
237+
238+
labels
239+
.drain(..)
240+
// the label style was only needed for sorting
241+
.map(|(file, _, start)| (file, start))
242+
// this also deduplicates
243+
.collect()
244+
}
210245
}

codespan-reporting/src/files.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ impl std::error::Error for Error {
8585
pub trait Files<'a> {
8686
/// A unique identifier for files in the file provider. This will be used
8787
/// for rendering `diagnostic::Label`s in the corresponding source files.
88-
type FileId: 'a + Copy + PartialEq;
88+
type FileId: 'a + Copy + Ord;
8989
/// The user-facing name of a file, to be displayed in diagnostics.
9090
type Name: 'a + std::fmt::Display;
9191
/// The source code of a file.

codespan-reporting/src/term/views.rs

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub struct RichDiagnostic<'diagnostic, 'config, FileId> {
2121

2222
impl<'diagnostic, 'config, FileId> RichDiagnostic<'diagnostic, 'config, FileId>
2323
where
24-
FileId: Copy + PartialEq,
24+
FileId: Copy + Ord,
2525
{
2626
pub fn new(
2727
diagnostic: &'diagnostic Diagnostic<FileId>,
@@ -42,12 +42,10 @@ where
4242

4343
struct LabeledFile<'diagnostic, FileId> {
4444
file_id: FileId,
45-
start: usize,
4645
name: String,
4746
location: Location,
4847
num_multi_labels: usize,
4948
lines: BTreeMap<usize, Line<'diagnostic>>,
50-
max_label_style: LabelStyle,
5149
}
5250

5351
impl<'diagnostic, FileId> LabeledFile<'diagnostic, FileId> {
@@ -83,6 +81,8 @@ where
8381
// snippets of source code.
8482
let mut outer_padding = 0;
8583

84+
let locuses = self.diagnostic.locuses();
85+
8686
// Group labels by file
8787
for label in &self.diagnostic.labels {
8888
let start_line_index = files.line_index(label.file_id, label.range.start)?;
@@ -102,29 +102,19 @@ where
102102
.iter_mut()
103103
.find(|labeled_file| label.file_id == labeled_file.file_id)
104104
{
105-
Some(labeled_file) => {
106-
// another diagnostic also referenced this file
107-
if labeled_file.max_label_style > label.style
108-
|| (labeled_file.max_label_style == label.style
109-
&& labeled_file.start > label.range.start)
110-
{
111-
// this label has a higher style or has the same style but starts earlier
112-
labeled_file.start = label.range.start;
113-
labeled_file.location = files.location(label.file_id, label.range.start)?;
114-
labeled_file.max_label_style = label.style;
115-
}
116-
labeled_file
117-
}
105+
Some(labeled_file) => labeled_file,
118106
None => {
107+
let location = *locuses
108+
.get(&label.file_id)
109+
.expect("file missing from locuses");
110+
119111
// no other diagnostic referenced this file yet
120112
labeled_files.push(LabeledFile {
121113
file_id: label.file_id,
122-
start: label.range.start,
123114
name: files.name(label.file_id)?.to_string(),
124-
location: files.location(label.file_id, label.range.start)?,
115+
location: files.location(label.file_id, location)?,
125116
num_multi_labels: 0,
126117
lines: BTreeMap::new(),
127-
max_label_style: label.style,
128118
});
129119
// this unwrap should never fail because we just pushed an element
130120
labeled_files

0 commit comments

Comments
 (0)