Skip to content

Commit 2bb67b8

Browse files
committed
Parse File ... not found messages
This will help us keep the module set in sync more reliably.
1 parent a93cc3f commit 2bb67b8

17 files changed

+841
-120
lines changed

src/ghci/parse/eval.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use miette::miette;
77
use winnow::ascii::line_ending;
88
use winnow::ascii::space0;
99
use winnow::combinator::alt;
10-
use winnow::combinator::eof;
1110
use winnow::combinator::opt;
1211
use winnow::combinator::peek;
1312
use winnow::combinator::repeat;
@@ -16,6 +15,7 @@ use winnow::Located;
1615
use winnow::PResult;
1716
use winnow::Parser;
1817

18+
use crate::ghci::parse::lines::line_ending_or_eof;
1919
use crate::ghci::GhciCommand;
2020

2121
use super::lines::rest_of_line;
@@ -173,7 +173,7 @@ fn multiline_eval_command(input: &mut Located<&str>) -> PResult<ByteSpanCommand>
173173
.with_span()
174174
.parse_next(input)?;
175175
multiline_eval_end.parse_next(input)?;
176-
let _ = (space0, alt((line_ending, eof))).parse_next(input)?;
176+
let _ = (space0, line_ending_or_eof).parse_next(input)?;
177177

178178
Ok(ByteSpanCommand {
179179
// `command` ends with a newline so we put a newline after the `:{` but not before the

src/ghci/parse/ghc_message/cant_find_file_diagnostic.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use crate::ghci::parse::lines::until_newline;
77

88
use crate::ghci::parse::ghc_message::position;
99
use crate::ghci::parse::ghc_message::severity;
10-
use crate::ghci::parse::ghc_message::GhcMessage;
1110

1211
use super::GhcDiagnostic;
1312

@@ -16,20 +15,20 @@ use super::GhcDiagnostic;
1615
/// ```plain
1716
/// <no location info>: error: can't find file: Why.hs
1817
/// ```
19-
pub fn cant_find_file_diagnostic(input: &mut &str) -> PResult<GhcMessage> {
18+
pub fn cant_find_file_diagnostic(input: &mut &str) -> PResult<GhcDiagnostic> {
2019
let _ = position::parse_unhelpful_position.parse_next(input)?;
2120
let _ = space1.parse_next(input)?;
2221
let severity = severity::parse_severity_colon.parse_next(input)?;
2322
let _ = space1.parse_next(input)?;
2423
let _ = "can't find file: ".parse_next(input)?;
2524
let path = until_newline.parse_next(input)?;
2625

27-
Ok(GhcMessage::Diagnostic(GhcDiagnostic {
26+
Ok(GhcDiagnostic {
2827
severity,
2928
path: Some(Utf8PathBuf::from(path)),
3029
span: Default::default(),
3130
message: "can't find file".to_owned(),
32-
}))
31+
})
3332
}
3433

3534
#[cfg(test)]
@@ -46,12 +45,12 @@ mod tests {
4645
cant_find_file_diagnostic
4746
.parse("<no location info>: error: can't find file: Why.hs\n")
4847
.unwrap(),
49-
GhcMessage::Diagnostic(GhcDiagnostic {
48+
GhcDiagnostic {
5049
severity: Severity::Error,
5150
path: Some("Why.hs".into()),
5251
span: Default::default(),
5352
message: "can't find file".to_owned()
54-
})
53+
}
5554
);
5655

5756
// Doesn't parse another error message.
@@ -71,8 +70,6 @@ mod tests {
7170
cant_find_file_diagnostic
7271
.parse("<no location info>: error: can't find file: Why.hs\n")
7372
.unwrap()
74-
.into_diagnostic()
75-
.unwrap()
7673
.to_string(),
7774
"Why.hs: error: can't find file"
7875
);

src/ghci/parse/ghc_message/compilation_summary.rs

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
use winnow::ascii::digit1;
2-
use winnow::ascii::line_ending;
32
use winnow::combinator::alt;
43
use winnow::combinator::opt;
54
use winnow::PResult;
65
use winnow::Parser;
76

7+
use crate::ghci::parse::lines::line_ending_or_eof;
88
use crate::ghci::parse::CompilationResult;
99

10-
use super::GhcMessage;
11-
1210
/// Compilation finished.
1311
///
1412
/// ```text
@@ -29,7 +27,7 @@ pub struct CompilationSummary {
2927
}
3028

3129
/// Parse a compilation summary, like `Ok, one module loaded.`.
32-
pub fn compilation_summary(input: &mut &str) -> PResult<GhcMessage> {
30+
pub fn compilation_summary(input: &mut &str) -> PResult<CompilationSummary> {
3331
let result = alt((
3432
"Ok".map(|_| CompilationResult::Ok),
3533
"Failed".map(|_| CompilationResult::Err),
@@ -54,12 +52,12 @@ pub fn compilation_summary(input: &mut &str) -> PResult<GhcMessage> {
5452
let _ = " module".parse_next(input)?;
5553
let _ = opt("s").parse_next(input)?;
5654
let _ = " loaded.".parse_next(input)?;
57-
let _ = line_ending.parse_next(input)?;
55+
let _ = line_ending_or_eof.parse_next(input)?;
5856

59-
Ok(GhcMessage::Summary(CompilationSummary {
57+
Ok(CompilationSummary {
6058
result,
6159
modules_loaded,
62-
}))
60+
})
6361
}
6462

6563
#[cfg(test)]
@@ -75,60 +73,60 @@ mod tests {
7573
compilation_summary
7674
.parse("Ok, 123 modules loaded.\n")
7775
.unwrap(),
78-
GhcMessage::Summary(CompilationSummary {
76+
CompilationSummary {
7977
result: CompilationResult::Ok,
8078
modules_loaded: 123,
81-
})
79+
}
8280
);
8381

8482
assert_eq!(
8583
compilation_summary
8684
.parse("Ok, no modules loaded.\n")
8785
.unwrap(),
88-
GhcMessage::Summary(CompilationSummary {
86+
CompilationSummary {
8987
result: CompilationResult::Ok,
9088
modules_loaded: 0,
91-
})
89+
}
9290
);
9391

9492
assert_eq!(
9593
compilation_summary
9694
.parse("Ok, one module loaded.\n")
9795
.unwrap(),
98-
GhcMessage::Summary(CompilationSummary {
96+
CompilationSummary {
9997
result: CompilationResult::Ok,
10098
modules_loaded: 1,
101-
})
99+
}
102100
);
103101

104102
assert_eq!(
105103
compilation_summary
106104
.parse("Ok, six modules loaded.\n")
107105
.unwrap(),
108-
GhcMessage::Summary(CompilationSummary {
106+
CompilationSummary {
109107
result: CompilationResult::Ok,
110108
modules_loaded: 6,
111-
})
109+
}
112110
);
113111

114112
assert_eq!(
115113
compilation_summary
116114
.parse("Failed, 7 modules loaded.\n")
117115
.unwrap(),
118-
GhcMessage::Summary(CompilationSummary {
116+
CompilationSummary {
119117
result: CompilationResult::Err,
120118
modules_loaded: 7,
121-
})
119+
}
122120
);
123121

124122
assert_eq!(
125123
compilation_summary
126124
.parse("Failed, one module loaded.\n")
127125
.unwrap(),
128-
GhcMessage::Summary(CompilationSummary {
126+
CompilationSummary {
129127
result: CompilationResult::Err,
130128
modules_loaded: 1,
131-
})
129+
}
132130
);
133131

134132
// Negative cases

src/ghci/parse/ghc_message/compiling.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use module_and_files::CompilingModule;
12
use winnow::ascii::digit1;
23
use winnow::ascii::space0;
34
use winnow::PResult;
@@ -6,10 +7,8 @@ use winnow::Parser;
67
use crate::ghci::parse::lines::rest_of_line;
78
use crate::ghci::parse::module_and_files;
89

9-
use super::GhcMessage;
10-
1110
/// Parse a `[1 of 3] Compiling Foo ( Foo.hs, Foo.o, interpreted )` message.
12-
pub fn compiling(input: &mut &str) -> PResult<GhcMessage> {
11+
pub fn compiling(input: &mut &str) -> PResult<CompilingModule> {
1312
let _ = "[".parse_next(input)?;
1413
let _ = space0.parse_next(input)?;
1514
let _ = digit1.parse_next(input)?;
@@ -20,7 +19,7 @@ pub fn compiling(input: &mut &str) -> PResult<GhcMessage> {
2019
let module = module_and_files.parse_next(input)?;
2120
let _ = rest_of_line.parse_next(input)?;
2221

23-
Ok(GhcMessage::Compiling(module))
22+
Ok(module)
2423
}
2524

2625
#[cfg(test)]
@@ -37,10 +36,10 @@ mod tests {
3736
compiling
3837
.parse("[1 of 3] Compiling Foo ( Foo.hs, Foo.o, interpreted )\n")
3938
.unwrap(),
40-
GhcMessage::Compiling(CompilingModule {
39+
CompilingModule {
4140
name: "Foo".into(),
4241
path: "Foo.hs".into()
43-
})
42+
}
4443
);
4544

4645
assert_eq!(
@@ -51,20 +50,20 @@ mod tests {
5150
/Users/wiggles/doggy-web-backend6/dist-newstyle/build/aarch64-osx/ghc-9.6.2/doggy-web-backend-0/l/test-dev/noopt/build/test-dev/A/DoggyPrelude/Puppy.dyn_o \
5251
) [Doggy.Lint package changed]\n")
5352
.unwrap(),
54-
GhcMessage::Compiling(CompilingModule {
53+
CompilingModule {
5554
name: "A.DoggyPrelude.Puppy".into(),
5655
path: "src/A/DoggyPrelude/Puppy.hs".into()
57-
})
56+
}
5857
);
5958

6059
assert_eq!(
6160
compiling
6261
.parse("[1 of 4] Compiling MyLib ( src/MyLib.hs )\n")
6362
.unwrap(),
64-
GhcMessage::Compiling(CompilingModule {
63+
CompilingModule {
6564
name: "MyLib".into(),
6665
path: "src/MyLib.hs".into()
67-
})
66+
}
6867
);
6968

7069
// Shouldn't parse multiple lines.

src/ghci/parse/ghc_message/generic_diagnostic.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use crate::ghci::parse::ghc_message::message_body::parse_message_body;
77
use crate::ghci::parse::ghc_message::path_colon;
88
use crate::ghci::parse::ghc_message::position;
99
use crate::ghci::parse::ghc_message::severity;
10-
use crate::ghci::parse::ghc_message::GhcMessage;
1110

1211
use super::GhcDiagnostic;
1312

@@ -23,7 +22,7 @@ use super::GhcDiagnostic;
2322
/// 6 | deriving MyClass
2423
/// | ^^^^^^^
2524
/// ```
26-
pub fn generic_diagnostic(input: &mut &str) -> PResult<GhcMessage> {
25+
pub fn generic_diagnostic(input: &mut &str) -> PResult<GhcDiagnostic> {
2726
// TODO: Confirm that the input doesn't start with space?
2827
let path = path_colon.parse_next(input)?;
2928
let span = position::parse_position_range.parse_next(input)?;
@@ -32,12 +31,12 @@ pub fn generic_diagnostic(input: &mut &str) -> PResult<GhcMessage> {
3231
let _ = space0.parse_next(input)?;
3332
let message = parse_message_body.parse_next(input)?;
3433

35-
Ok(GhcMessage::Diagnostic(GhcDiagnostic {
34+
Ok(GhcDiagnostic {
3635
severity,
3736
path: Some(path.to_owned()),
3837
span,
3938
message: message.to_owned(),
40-
}))
39+
})
4140
}
4241

4342
#[cfg(test)]
@@ -65,7 +64,7 @@ mod tests {
6564
"
6665
))
6766
.unwrap(),
68-
GhcMessage::Diagnostic(GhcDiagnostic {
67+
GhcDiagnostic {
6968
severity: Severity::Error,
7069
path: Some("NotStockDeriveable.hs".into()),
7170
span: PositionRange::new(6, 12, 6, 12),
@@ -81,7 +80,7 @@ mod tests {
8180
"
8281
)
8382
.into()
84-
})
83+
}
8584
);
8685

8786
// Doesn't parse another error message.

src/ghci/parse/ghc_message/mod.rs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub use position::PositionRange;
1414
mod severity;
1515
pub use severity::Severity;
1616

17-
mod single_quote;
17+
mod single_quoted;
1818

1919
mod path_colon;
2020
use path_colon::path_colon;
@@ -43,6 +43,10 @@ use module_import_cycle_diagnostic::module_import_cycle_diagnostic;
4343
mod no_location_info_diagnostic;
4444
use no_location_info_diagnostic::no_location_info_diagnostic;
4545

46+
mod not_found;
47+
use not_found::not_found;
48+
pub use not_found::NotFound;
49+
4650
use super::rest_of_line;
4751
use super::CompilingModule;
4852

@@ -51,6 +55,13 @@ use super::CompilingModule;
5155
/// These include progress updates on compilation, errors and warnings, or GHCi messages.
5256
#[derive(Debug, Clone, PartialEq, Eq)]
5357
pub enum GhcMessage {
58+
/// A module or file was not found.
59+
///
60+
/// ```text
61+
/// File src/Foo.hs not found
62+
/// Module Foo not found
63+
/// ```
64+
NotFound(NotFound),
5465
/// A module being compiled.
5566
///
5667
/// ```text
@@ -167,13 +178,20 @@ fn parse_messages_inner(input: &mut &str) -> PResult<Vec<GhcMessage>> {
167178
repeat(
168179
0..,
169180
alt((
170-
compiling.map(Item::One),
171-
generic_diagnostic.map(Item::One),
172-
cant_find_file_diagnostic.map(Item::One),
173-
no_location_info_diagnostic.map(Item::One),
181+
compiling.map(GhcMessage::Compiling).map(Item::One),
182+
generic_diagnostic
183+
.map(GhcMessage::Diagnostic)
184+
.map(Item::One),
185+
compilation_summary.map(GhcMessage::Summary).map(Item::One),
186+
not_found.map(GhcMessage::NotFound).map(Item::One),
187+
cant_find_file_diagnostic
188+
.map(GhcMessage::Diagnostic)
189+
.map(Item::One),
190+
no_location_info_diagnostic
191+
.map(GhcMessage::Diagnostic)
192+
.map(Item::One),
174193
module_import_cycle_diagnostic.map(Item::Many),
175194
loaded_configuration.map(Item::One),
176-
compilation_summary.map(Item::One),
177195
rest_of_line.map(|line| {
178196
tracing::debug!(line, "Ignoring GHC output line");
179197
Item::Ignore
@@ -213,6 +231,10 @@ mod tests {
213231
Preprocessing library 'test-dev' for my-simple-package-0.1.0.0..
214232
GHCi, version 9.0.2: https://www.haskell.org/ghc/ :? for help
215233
Loaded GHCi configuration from /Users/wiggles/.ghci
234+
File src/Puppy.hs not found
235+
File src/
236+
Puppy.hs not found
237+
Module Puppy.Doggy not found
216238
[1 of 4] Compiling MyLib ( src/MyLib.hs, interpreted )
217239
[2 of 4] Compiling MyModule ( src/MyModule.hs, interpreted )
218240
@@ -233,6 +255,9 @@ mod tests {
233255
GhcMessage::LoadConfig {
234256
path: "/Users/wiggles/.ghci".into()
235257
},
258+
GhcMessage::NotFound(NotFound::File("src/Puppy.hs".into())),
259+
GhcMessage::NotFound(NotFound::File("src/\nPuppy.hs".into())),
260+
GhcMessage::NotFound(NotFound::Module("Puppy.Doggy".into())),
236261
GhcMessage::Compiling(CompilingModule {
237262
name: "MyLib".into(),
238263
path: "src/MyLib.hs".into(),

0 commit comments

Comments
 (0)