compiletest: Stricter parsing for diagnostic kinds
This commit is contained in:
parent
b86b3fb640
commit
5c160f511e
16 changed files with 74 additions and 72 deletions
|
|
@ -3,7 +3,6 @@ use std::fs::File;
|
|||
use std::io::BufReader;
|
||||
use std::io::prelude::*;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use regex::Regex;
|
||||
|
|
@ -18,30 +17,39 @@ pub enum ErrorKind {
|
|||
Warning,
|
||||
}
|
||||
|
||||
impl FromStr for ErrorKind {
|
||||
type Err = ();
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let s = s.to_uppercase();
|
||||
let part0: &str = s.split(':').next().unwrap();
|
||||
match part0 {
|
||||
"HELP" => Ok(ErrorKind::Help),
|
||||
"ERROR" => Ok(ErrorKind::Error),
|
||||
"NOTE" => Ok(ErrorKind::Note),
|
||||
"SUGGESTION" => Ok(ErrorKind::Suggestion),
|
||||
"WARN" | "WARNING" => Ok(ErrorKind::Warning),
|
||||
_ => Err(()),
|
||||
impl ErrorKind {
|
||||
pub fn from_compiler_str(s: &str) -> ErrorKind {
|
||||
match s {
|
||||
"help" => ErrorKind::Help,
|
||||
"error" | "error: internal compiler error" => ErrorKind::Error,
|
||||
"note" | "failure-note" => ErrorKind::Note,
|
||||
"warning" => ErrorKind::Warning,
|
||||
_ => panic!("unexpected compiler diagnostic kind `{s}`"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Either the canonical uppercase string, or some additional versions for compatibility.
|
||||
/// FIXME: consider keeping only the canonical versions here.
|
||||
fn from_user_str(s: &str) -> Option<ErrorKind> {
|
||||
Some(match s {
|
||||
"HELP" | "help" => ErrorKind::Help,
|
||||
"ERROR" | "error" => ErrorKind::Error,
|
||||
"NOTE" | "note" => ErrorKind::Note,
|
||||
"SUGGESTION" => ErrorKind::Suggestion,
|
||||
"WARN" | "WARNING" | "warn" | "warning" => ErrorKind::Warning,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ErrorKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
ErrorKind::Help => write!(f, "help message"),
|
||||
ErrorKind::Error => write!(f, "error"),
|
||||
ErrorKind::Note => write!(f, "note"),
|
||||
ErrorKind::Suggestion => write!(f, "suggestion"),
|
||||
ErrorKind::Warning => write!(f, "warning"),
|
||||
ErrorKind::Help => write!(f, "HELP"),
|
||||
ErrorKind::Error => write!(f, "ERROR"),
|
||||
ErrorKind::Note => write!(f, "NOTE"),
|
||||
ErrorKind::Suggestion => write!(f, "SUGGESTION"),
|
||||
ErrorKind::Warning => write!(f, "WARN"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -64,7 +72,7 @@ impl Error {
|
|||
use colored::Colorize;
|
||||
format!(
|
||||
"{: <10}line {: >3}: {}",
|
||||
self.kind.map(|kind| kind.to_string()).unwrap_or_default().to_uppercase(),
|
||||
self.kind.map(|kind| kind.to_string()).unwrap_or_default(),
|
||||
self.line_num_str(),
|
||||
self.msg.cyan(),
|
||||
)
|
||||
|
|
@ -154,18 +162,12 @@ fn parse_expected(
|
|||
}
|
||||
|
||||
// Get the part of the comment after the sigil (e.g. `~^^` or ~|).
|
||||
let whole_match = captures.get(0).unwrap();
|
||||
let (_, mut msg) = line.split_at(whole_match.end());
|
||||
|
||||
let first_word = msg.split_whitespace().next().expect("Encountered unexpected empty comment");
|
||||
|
||||
// If we find `//~ ERROR foo` or something like that, skip the first word.
|
||||
let kind = first_word.parse::<ErrorKind>().ok();
|
||||
if kind.is_some() {
|
||||
msg = &msg.trim_start().split_at(first_word.len()).1;
|
||||
}
|
||||
|
||||
let msg = msg.trim().to_owned();
|
||||
let tag = captures.get(0).unwrap();
|
||||
let rest = line[tag.end()..].trim_start();
|
||||
let (kind_str, _) = rest.split_once(|c: char| !c.is_ascii_alphabetic()).unwrap_or((rest, ""));
|
||||
let kind = ErrorKind::from_user_str(kind_str);
|
||||
let untrimmed_msg = if kind.is_some() { &rest[kind_str.len()..] } else { rest };
|
||||
let msg = untrimmed_msg.strip_prefix(':').unwrap_or(untrimmed_msg).trim().to_owned();
|
||||
|
||||
let line_num_adjust = &captures["adjust"];
|
||||
let (follow_prev, line_num) = if line_num_adjust == "|" {
|
||||
|
|
@ -181,7 +183,7 @@ fn parse_expected(
|
|||
debug!(
|
||||
"line={:?} tag={:?} follow_prev={:?} kind={:?} msg={:?}",
|
||||
line_num,
|
||||
whole_match.as_str(),
|
||||
tag.as_str(),
|
||||
follow_prev,
|
||||
kind,
|
||||
msg
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
//! These structs are a subset of the ones found in `rustc_errors::json`.
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use regex::Regex;
|
||||
|
|
@ -230,7 +229,7 @@ fn push_actual_errors(
|
|||
// Convert multi-line messages into multiple errors.
|
||||
// We expect to replace these with something more structured anyhow.
|
||||
let mut message_lines = diagnostic.message.lines();
|
||||
let kind = ErrorKind::from_str(&diagnostic.level).ok();
|
||||
let kind = Some(ErrorKind::from_compiler_str(&diagnostic.level));
|
||||
let first_line = message_lines.next().unwrap_or(&diagnostic.message);
|
||||
if primary_spans.is_empty() {
|
||||
static RE: OnceLock<Regex> = OnceLock::new();
|
||||
|
|
@ -240,7 +239,8 @@ fn push_actual_errors(
|
|||
line_num: None,
|
||||
kind,
|
||||
msg: with_code(None, first_line),
|
||||
require_annotation: !RE.get_or_init(re_init).is_match(first_line),
|
||||
require_annotation: diagnostic.level != "failure-note"
|
||||
&& !RE.get_or_init(re_init).is_match(first_line),
|
||||
});
|
||||
} else {
|
||||
for span in primary_spans {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue