2222import com .palantir .witchcraft .java .logging .format .LogParser ;
2323import java .io .File ;
2424import java .io .IOException ;
25- import java .io .StringWriter ;
25+ import java .io .UncheckedIOException ;
2626import java .io .Writer ;
27+ import java .util .function .BiConsumer ;
2728import org .gradle .api .Action ;
2829import org .gradle .api .internal .tasks .testing .junit .result .TestClassResult ;
2930import org .gradle .api .internal .tasks .testing .junit .result .TestResultsProvider ;
@@ -58,9 +59,24 @@ private static final class FormattingTestResultsProvider implements TestResultsP
5859 (include , formatted ) -> include
5960 ? writer -> {
6061 writer .write (formatted );
61- writer .write (" \n " );
62+ writer .write ('\n' );
6263 }
6364 : Writable .NOP ));
65+ private static final BiConsumer <String , Writer > LINE_PROCESSOR = (line , outputWriter ) -> {
66+ try {
67+ PARSER .tryParse (line )
68+ .orElseGet (() -> out -> {
69+ try {
70+ out .write (line );
71+ } catch (IOException e ) {
72+ throw new UncheckedIOException (e );
73+ }
74+ })
75+ .write (outputWriter );
76+ } catch (IOException e ) {
77+ throw new UncheckedIOException (e );
78+ }
79+ };
6480
6581 private final TestResultsProvider delegate ;
6682
@@ -69,30 +85,58 @@ private static final class FormattingTestResultsProvider implements TestResultsP
6985 }
7086
7187 @ Override
72- @ SuppressWarnings ("StringSplitter" )
7388 public void writeAllOutput (long classId , TestOutputEvent .Destination destination , Writer writer ) {
7489 if (destination == TestOutputEvent .Destination .StdErr
7590 || destination == TestOutputEvent .Destination .StdOut ) {
76- StringWriter stringWriter = new StringWriter ();
77- delegate .writeAllOutput (classId , destination , stringWriter );
78- String contents = stringWriter .toString ();
79- for (String line : contents .split ("\n " )) {
80- try {
81- PARSER .tryParse (line )
82- .orElseGet (() -> out -> {
83- out .write (line );
84- out .write ("\n " );
85- })
86- .write (writer );
87- } catch (IOException e ) {
88- throw new RuntimeException (e );
89- }
90- }
91+ delegate .writeAllOutput (classId , destination , new LineProcessingWriter (writer , LINE_PROCESSOR ));
9192 } else {
9293 delegate .writeAllOutput (classId , destination , writer );
9394 }
9495 }
9596
97+ private static class LineProcessingWriter extends Writer {
98+ private final Writer delegate ;
99+ private final BiConsumer <String , Writer > lineProcessor ;
100+ private final StringBuilder lineBuffer = new StringBuilder ();
101+
102+ LineProcessingWriter (Writer delegate , BiConsumer <String , Writer > lineProcessor ) {
103+ this .delegate = delegate ;
104+ this .lineProcessor = lineProcessor ;
105+ }
106+
107+ @ Override
108+ public void write (char [] cbuf , int off , int len ) throws IOException {
109+ for (int i = off ; i < off + len ; i ++) {
110+ char ch = cbuf [i ];
111+ if (ch == '\n' ) {
112+ processLine ();
113+ } else {
114+ lineBuffer .append (ch );
115+ }
116+ }
117+ }
118+
119+ @ Override
120+ public void flush () throws IOException {
121+ delegate .flush ();
122+ }
123+
124+ @ Override
125+ public void close () throws IOException {
126+ if (!lineBuffer .isEmpty ()) {
127+ processLine ();
128+ }
129+ delegate .close ();
130+ }
131+
132+ private void processLine () throws IOException {
133+ String line = lineBuffer .toString ();
134+ lineProcessor .accept (line , delegate );
135+ delegate .write ('\n' );
136+ lineBuffer .setLength (0 );
137+ }
138+ }
139+
96140 @ Override
97141 public void writeNonTestOutput (long classId , TestOutputEvent .Destination destination , Writer writer ) {
98142 delegate .writeNonTestOutput (classId , destination , writer );
0 commit comments