span: move MultiSpan
`MultiSpan` contains labels, which are more complicated with the introduction of diagnostic translation and will use types from `rustc_errors` - however, `rustc_errors` depends on `rustc_span` so `rustc_span` cannot use types like `DiagnosticMessage` without dependency cycles. Introduce a new `rustc_error_messages` crate that can contain `DiagnosticMessage` and `MultiSpan`. Signed-off-by: David Wood <david.wood@huawei.com>
This commit is contained in:
parent
8c684563a5
commit
c45f29595d
66 changed files with 354 additions and 293 deletions
|
@ -520,20 +520,6 @@ impl Ord for Span {
|
|||
}
|
||||
}
|
||||
|
||||
/// A collection of `Span`s.
|
||||
///
|
||||
/// Spans have two orthogonal attributes:
|
||||
///
|
||||
/// - They can be *primary spans*. In this case they are the locus of
|
||||
/// the error, and would be rendered with `^^^`.
|
||||
/// - They can have a *label*. In this case, the label is written next
|
||||
/// to the mark in the snippet when we render.
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq, Encodable, Decodable)]
|
||||
pub struct MultiSpan {
|
||||
primary_spans: Vec<Span>,
|
||||
span_labels: Vec<(Span, String)>,
|
||||
}
|
||||
|
||||
impl Span {
|
||||
#[inline]
|
||||
pub fn lo(self) -> BytePos {
|
||||
|
@ -949,20 +935,6 @@ impl Span {
|
|||
}
|
||||
}
|
||||
|
||||
/// A span together with some additional data.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SpanLabel {
|
||||
/// The span we are going to include in the final snippet.
|
||||
pub span: Span,
|
||||
|
||||
/// Is this a primary span? This is the "locus" of the message,
|
||||
/// and is indicated with a `^^^^` underline, versus `----`.
|
||||
pub is_primary: bool,
|
||||
|
||||
/// What label should we attach to this span (if any)?
|
||||
pub label: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for Span {
|
||||
fn default() -> Self {
|
||||
DUMMY_SP
|
||||
|
@ -1035,115 +1007,6 @@ impl fmt::Debug for SpanData {
|
|||
}
|
||||
}
|
||||
|
||||
impl MultiSpan {
|
||||
#[inline]
|
||||
pub fn new() -> MultiSpan {
|
||||
MultiSpan { primary_spans: vec![], span_labels: vec![] }
|
||||
}
|
||||
|
||||
pub fn from_span(primary_span: Span) -> MultiSpan {
|
||||
MultiSpan { primary_spans: vec![primary_span], span_labels: vec![] }
|
||||
}
|
||||
|
||||
pub fn from_spans(mut vec: Vec<Span>) -> MultiSpan {
|
||||
vec.sort();
|
||||
MultiSpan { primary_spans: vec, span_labels: vec![] }
|
||||
}
|
||||
|
||||
pub fn push_span_label(&mut self, span: Span, label: String) {
|
||||
self.span_labels.push((span, label));
|
||||
}
|
||||
|
||||
/// Selects the first primary span (if any).
|
||||
pub fn primary_span(&self) -> Option<Span> {
|
||||
self.primary_spans.first().cloned()
|
||||
}
|
||||
|
||||
/// Returns all primary spans.
|
||||
pub fn primary_spans(&self) -> &[Span] {
|
||||
&self.primary_spans
|
||||
}
|
||||
|
||||
/// Returns `true` if any of the primary spans are displayable.
|
||||
pub fn has_primary_spans(&self) -> bool {
|
||||
self.primary_spans.iter().any(|sp| !sp.is_dummy())
|
||||
}
|
||||
|
||||
/// Returns `true` if this contains only a dummy primary span with any hygienic context.
|
||||
pub fn is_dummy(&self) -> bool {
|
||||
let mut is_dummy = true;
|
||||
for span in &self.primary_spans {
|
||||
if !span.is_dummy() {
|
||||
is_dummy = false;
|
||||
}
|
||||
}
|
||||
is_dummy
|
||||
}
|
||||
|
||||
/// Replaces all occurrences of one Span with another. Used to move `Span`s in areas that don't
|
||||
/// display well (like std macros). Returns whether replacements occurred.
|
||||
pub fn replace(&mut self, before: Span, after: Span) -> bool {
|
||||
let mut replacements_occurred = false;
|
||||
for primary_span in &mut self.primary_spans {
|
||||
if *primary_span == before {
|
||||
*primary_span = after;
|
||||
replacements_occurred = true;
|
||||
}
|
||||
}
|
||||
for span_label in &mut self.span_labels {
|
||||
if span_label.0 == before {
|
||||
span_label.0 = after;
|
||||
replacements_occurred = true;
|
||||
}
|
||||
}
|
||||
replacements_occurred
|
||||
}
|
||||
|
||||
/// Returns the strings to highlight. We always ensure that there
|
||||
/// is an entry for each of the primary spans -- for each primary
|
||||
/// span `P`, if there is at least one label with span `P`, we return
|
||||
/// those labels (marked as primary). But otherwise we return
|
||||
/// `SpanLabel` instances with empty labels.
|
||||
pub fn span_labels(&self) -> Vec<SpanLabel> {
|
||||
let is_primary = |span| self.primary_spans.contains(&span);
|
||||
|
||||
let mut span_labels = self
|
||||
.span_labels
|
||||
.iter()
|
||||
.map(|&(span, ref label)| SpanLabel {
|
||||
span,
|
||||
is_primary: is_primary(span),
|
||||
label: Some(label.clone()),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for &span in &self.primary_spans {
|
||||
if !span_labels.iter().any(|sl| sl.span == span) {
|
||||
span_labels.push(SpanLabel { span, is_primary: true, label: None });
|
||||
}
|
||||
}
|
||||
|
||||
span_labels
|
||||
}
|
||||
|
||||
/// Returns `true` if any of the span labels is displayable.
|
||||
pub fn has_span_labels(&self) -> bool {
|
||||
self.span_labels.iter().any(|(sp, _)| !sp.is_dummy())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Span> for MultiSpan {
|
||||
fn from(span: Span) -> MultiSpan {
|
||||
MultiSpan::from_span(span)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<Span>> for MultiSpan {
|
||||
fn from(spans: Vec<Span>) -> MultiSpan {
|
||||
MultiSpan::from_spans(spans)
|
||||
}
|
||||
}
|
||||
|
||||
/// Identifies an offset of a multi-byte character in a `SourceFile`.
|
||||
#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug)]
|
||||
pub struct MultiByteChar {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue