]>
git.proxmox.com Git - rustc.git/blob - src/tools/compiletest/src/errors.rs
1 use self::WhichLine
::*;
5 use std
::io
::prelude
::*;
6 use std
::io
::BufReader
;
10 use lazy_static
::lazy_static
;
14 #[derive(Clone, Debug, PartialEq)]
23 impl FromStr
for ErrorKind
{
25 fn from_str(s
: &str) -> Result
<Self, Self::Err
> {
26 let s
= s
.to_uppercase();
27 let part0
: &str = s
.split('
:'
).next().unwrap();
29 "HELP" => Ok(ErrorKind
::Help
),
30 "ERROR" => Ok(ErrorKind
::Error
),
31 "NOTE" => Ok(ErrorKind
::Note
),
32 "SUGGESTION" => Ok(ErrorKind
::Suggestion
),
33 "WARN" | "WARNING" => Ok(ErrorKind
::Warning
),
39 impl fmt
::Display
for ErrorKind
{
40 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
42 ErrorKind
::Help
=> write
!(f
, "help message"),
43 ErrorKind
::Error
=> write
!(f
, "error"),
44 ErrorKind
::Note
=> write
!(f
, "note"),
45 ErrorKind
::Suggestion
=> write
!(f
, "suggestion"),
46 ErrorKind
::Warning
=> write
!(f
, "warning"),
54 /// What kind of message we expect (e.g., warning, error, suggestion).
55 /// `None` if not specified or unknown message kind.
56 pub kind
: Option
<ErrorKind
>,
60 #[derive(PartialEq, Debug)]
63 FollowPrevious(usize),
64 AdjustBackward(usize),
67 /// Looks for either "//~| KIND MESSAGE" or "//~^^... KIND MESSAGE"
68 /// The former is a "follow" that inherits its target from the preceding line;
69 /// the latter is an "adjusts" that goes that many lines up.
71 /// Goal is to enable tests both like: //~^^^ ERROR go up three
72 /// and also //~^ ERROR message one for the preceding line, and
73 /// //~| ERROR message two for that same line.
75 /// If cfg is not None (i.e., in an incremental test), then we look
76 /// for `//[X]~` instead, where `X` is the current `cfg`.
77 pub fn load_errors(testfile
: &Path
, cfg
: Option
<&str>) -> Vec
<Error
> {
78 let rdr
= BufReader
::new(File
::open(testfile
).unwrap());
80 // `last_nonfollow_error` tracks the most recently seen
81 // line with an error template that did not use the
82 // follow-syntax, "//~| ...".
84 // (pnkfelix could not find an easy way to compose Iterator::scan
85 // and Iterator::filter_map to pass along this information into
86 // `parse_expected`. So instead I am storing that state here and
87 // updating it in the map callback below.)
88 let mut last_nonfollow_error
= None
;
92 .filter_map(|(line_num
, line
)| {
93 parse_expected(last_nonfollow_error
, line_num
+ 1, &line
.unwrap(), cfg
).map(
96 FollowPrevious(_
) => {}
97 _
=> last_nonfollow_error
= Some(error
.line_num
),
108 last_nonfollow_error
: Option
<usize>,
112 ) -> Option
<(WhichLine
, Error
)> {
113 // Matches comments like:
121 static ref RE
: Regex
=
122 Regex
::new(r
"//(?:\[(?P<cfgs>[\w,]+)])?~(?P<adjust>\||\^*)").unwrap();
125 let captures
= RE
.captures(line
)?
;
127 match (cfg
, captures
.name("cfgs")) {
128 // Only error messages that contain our `cfg` betweeen the square brackets apply to us.
129 (Some(cfg
), Some(filter
)) if !filter
.as_str().split('
,'
).any(|s
| s
== cfg
)
131 (Some(_
), Some(_
)) => {}
133 (None
, Some(_
)) => panic
!("Only tests with revisions should use `//[X]~`"),
135 // If an error has no list of revisions, it applies to all revisions.
136 (Some(_
), None
) | (None
, None
) => {}
139 let (follow
, adjusts
) = match &captures
["adjust"] {
141 circumflexes
=> (false, circumflexes
.len()),
144 // Get the part of the comment after the sigil (e.g. `~^^` or ~|).
145 let whole_match
= captures
.get(0).unwrap();
146 let (_
, mut msg
) = line
.split_at(whole_match
.end());
151 .expect("Encountered unexpected empty comment");
153 // If we find `//~ ERROR foo` or something like that, skip the first word.
154 let kind
= first_word
.parse
::<ErrorKind
>().ok();
155 if let Some(_
) = kind
{
156 msg
= &msg
.trim_start().split_at(first_word
.len()).1;
159 let msg
= msg
.trim().to_owned();
161 let (which
, line_num
) = if follow
{
162 assert_eq
!(adjusts
, 0, "use either //~| or //~^, not both.");
163 let line_num
= last_nonfollow_error
.expect(
164 "encountered //~| without \
165 preceding //~^ line.",
167 (FollowPrevious(line_num
), line_num
)
169 let which
= if adjusts
> 0 {
170 AdjustBackward(adjusts
)
174 let line_num
= line_num
- adjusts
;
179 "line={} tag={:?} which={:?} kind={:?} msg={:?}",
180 line_num
, whole_match
.as_str(), which
, kind
, msg