diff --git a/src/logger.rs b/src/logger.rs index 89fa3d2..bede9ec 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -1,4 +1,4 @@ -use crate::parser::{parse, XCLOG_MATCHER}; +use crate::parser::{parse, XCOutput, XCOutputTask, XCLOG_MATCHER}; use crate::XCCompileCommand; use anyhow::Result; use async_stream::stream; @@ -31,41 +31,22 @@ impl ProcessExt for XCLogger { fn spawn_and_stream( &mut self, ) -> std::io::Result + Send>>> { - let mut output_stream = self._spawn_and_stream()?; - let compile_commands = self.compile_commands.clone(); + let process_stream = self._spawn_and_stream()?; + let mut output_stream = self.process_stream(process_stream); Ok(stream! { - let mut compile_commands = compile_commands.lock().await; while let Some(output) = output_stream.next().await { - match output { - ProcessItem::Error(line) => { - match parse(line, &mut output_stream).await { - Ok(Some(lines)) => { - for line in lines.into_iter() { - yield ProcessItem::Error(line.to_string()) - } }, - Err(e) => tracing::error!("ParseError: {e}"), - _ => () - } - }, - ProcessItem::Output(line) => { - if let Some(cmd) = XCLOG_MATCHER.get_compile_command(line.as_str()).and_then(XCCompileCommand::from_compile_command_data) { - compile_commands.push(cmd); - } else { - match parse(line, &mut output_stream).await { - Ok(Some(lines)) => { - for line in lines.into_iter() { - yield ProcessItem::Output(line.to_string()) - } }, - Err(e) => tracing::error!("ParseError: {e}"), - _ => () - } - } - - }, - output => yield output - } - } + match output.kind { + XCOutputTask::Task | XCOutputTask::Test | XCOutputTask::Warning => { + yield ProcessItem::Output(output.to_string()) + } + XCOutputTask::Error => yield ProcessItem::Error(output.to_string()), + XCOutputTask::Exit => yield ProcessItem::Exit(output.value), + XCOutputTask::Result => { + yield ProcessItem::Output(output.to_string()) + } + }; + }; } .boxed()) } @@ -99,4 +80,82 @@ impl XCLogger { compile_commands: Default::default(), }) } + + pub(crate) fn process_stream( + &self, + mut output_stream: Pin + Send>>, + ) -> Pin + Send>> { + let compile_commands = self.compile_commands.clone(); + + stream! { + let mut compile_commands = compile_commands.lock().await; + while let Some(output) = output_stream.next().await { + + // Try to process compile command first + if let ProcessItem::Output(line) = &output { + if let Some(cmd) = XCLOG_MATCHER + .get_compile_command(line.as_str()) + .and_then(XCCompileCommand::from_compile_command_data) + { + compile_commands.push(cmd); + continue; + }; + }; + + match output { + ProcessItem::Error(line) => { + match parse(line, &mut output_stream).await { + Ok(Some(lines)) => { + for output in lines.into_iter() { + yield output + } }, + Err(e) => tracing::error!("ParseError: {e}"), + _ => () + } + }, + ProcessItem::Output(line) => { + match parse(line, &mut output_stream).await { + Ok(Some(outputs)) => { + for output in outputs.into_iter() { + yield output + } }, + Err(e) => tracing::error!("ParseError: {e}"), + _ => () + } + + }, + ProcessItem::Exit(exit) => { + let value = exit.trim(); + yield XCOutput { + kind: XCOutputTask::Exit, + value: value.into() + }; + } + } + } + } + .boxed() + } +} + +#[tokio::test] +#[tracing_test::traced_test] +async fn case_d() { + let logger = XCLogger::new("", [""]).expect("Create logger"); + let stream = stream! { + let content = include_str!("../tests/case_d.log"); + let lines = content.split("\n"); + for line in lines { + yield ProcessItem::Output(line.to_string()) + } + } + .boxed(); + let error_outputs = logger + .process_stream(stream) + .collect::>() + .await + .into_iter() + .filter(|t| t.is_error()) + .collect::>(); + assert_eq!(error_outputs.len(), 0, "{error_outputs:#?}") } diff --git a/src/parser/defs.rs b/src/parser/defs.rs index 6c51345..c855065 100644 --- a/src/parser/defs.rs +++ b/src/parser/defs.rs @@ -249,6 +249,23 @@ define! [ } } }, +{ + ident: SwiftCompile, + kind: Task, + desc: r"SwiftCompile", + captures: [ arch, filename, project, target ], + format: "[{target}] Compiling {filename}", + pattern: r"SwiftCompile\s(?P\S+)\s(?P.+/)(?P[^/]+)\s\(in\starget\s'(?P.*)'\sfrom\sproject\s'(?P.*)'\)", + tests: { + "SwiftCompile normal arm64 /source/Home/State/HomeStateAction.swift (in target 'xxx' from project 'xxx')" => + |captures| { + assert_eq!("normal", &captures["arch"]); + assert_eq!("HomeStateAction.swift", &captures["filename"]); + assert_eq!("xxx", &captures["project"]); + assert_eq!("xxx", &captures["target"]); + } + } +}, { ident: CompileStoryboard, kind: Task, @@ -968,7 +985,7 @@ define! [ desc: r"duplicate symbols location", captures: [ message ], format: "{message}", - pattern: r"\s+(?P/.*\.o[\)]?)$", + pattern: r" (?P/.*\.o[\)]?)$", tests: {} }, { diff --git a/src/parser/output.rs b/src/parser/output.rs index 78633df..6641d83 100644 --- a/src/parser/output.rs +++ b/src/parser/output.rs @@ -1,5 +1,5 @@ /// Kinds of outputs -#[derive(Clone, derive_is_enum_variant::is_enum_variant)] +#[derive(Clone, derive_is_enum_variant::is_enum_variant, Debug)] pub enum XCOutputTask { /// Task like Compile, Mkdir .. Task, @@ -11,10 +11,12 @@ pub enum XCOutputTask { Error, /// End Result Result, + /// Process exit + Exit } /// Formatted results of a given match -#[derive(Clone, derive_deref_rs::Deref)] +#[derive(Clone, derive_deref_rs::Deref, Debug)] pub struct XCOutput { #[deref] /// output value