65
65
import java .util .Properties ;
66
66
import java .util .StringTokenizer ;
67
67
import java .util .concurrent .ConcurrentLinkedDeque ;
68
+ import java .util .regex .Pattern ;
68
69
69
70
import org .codehaus .plexus .compiler .AbstractCompiler ;
70
71
import org .codehaus .plexus .compiler .CompilerConfiguration ;
@@ -627,6 +628,16 @@ private static CompilerResult compileInProcess0(Class<?> javacClass, String[] ar
627
628
return new CompilerResult (success , messages );
628
629
}
629
630
631
+ // Match ~95% of existing JDK exception name patterns (last checked for JDK 21)
632
+ private static final Pattern STACK_TRACE_FIRST_LINE = Pattern .compile ("^(?:[\\ w+.-]+\\ .)[\\ w$]*?(?:"
633
+ + "Exception|Error|Throwable|Failure|Result|Abort|Fault|ThreadDeath|Overflow|Warning|"
634
+ + "NotSupported|NotFound|BadArgs|BadClassFile|Illegal|Invalid|Unexpected|Unchecked|Unmatched\\ w+"
635
+ + ").*$" );
636
+
637
+ // Match exception causes, existing and omitted stack trace elements
638
+ private static final Pattern STACK_TRACE_OTHER_LINE =
639
+ Pattern .compile ("^(?:Caused by:\\ s.*|\\ s*at .*|\\ s*\\ .\\ .\\ .\\ s\\ d+\\ smore)$" );
640
+
630
641
/**
631
642
* Parse the output from the compiler into a list of CompilerMessage objects
632
643
*
@@ -643,6 +654,7 @@ static List<CompilerMessage> parseModernStream(int exitCode, BufferedReader inpu
643
654
StringBuilder buffer = new StringBuilder ();
644
655
645
656
boolean hasPointer = false ;
657
+ int stackTraceLineCount = 0 ;
646
658
647
659
while (true ) {
648
660
line = input .readLine ();
@@ -659,26 +671,44 @@ static List<CompilerMessage> parseModernStream(int exitCode, BufferedReader inpu
659
671
} else if (hasPointer ) {
660
672
// A compiler message remains in buffer at end of parse stream
661
673
errors .add (parseModernError (exitCode , bufferAsString ));
674
+ } else if (stackTraceLineCount > 0 ) {
675
+ // Extract stack trace from end of buffer
676
+ String [] lines = bufferAsString .split ("\\ R" );
677
+ int linesTotal = lines .length ;
678
+ buffer = new StringBuilder ();
679
+ int firstLine = linesTotal - stackTraceLineCount ;
680
+
681
+ // Salvage Javac localized message 'javac.msg.bug' ("An exception has occurred in the
682
+ // compiler ... Please file a bug")
683
+ if (firstLine > 0 ) {
684
+ final String lineBeforeStackTrace = lines [firstLine - 1 ];
685
+ // One of those two URL substrings should always appear, without regard to JVM locale.
686
+ // TODO: Update, if the URL changes, last checked for JDK 21.
687
+ if (lineBeforeStackTrace .contains ("java.sun.com/webapps/bugreport" )
688
+ || lineBeforeStackTrace .contains ("bugreport.java.com" )) {
689
+ firstLine --;
690
+ }
691
+ }
692
+
693
+ // Note: For message 'javac.msg.proc.annotation.uncaught.exception' ("An annotation processor
694
+ // threw an uncaught exception"), there is no locale-independent substring, and the header is
695
+ // also multi-line. It was discarded in the removed method 'parseAnnotationProcessorStream',
696
+ // and we continue to do so.
697
+
698
+ for (int i = firstLine ; i < linesTotal ; i ++) {
699
+ buffer .append (lines [i ]).append (EOL );
700
+ }
701
+ errors .add (new CompilerMessage (buffer .toString (), CompilerMessage .Kind .ERROR ));
662
702
}
663
703
}
664
704
return errors ;
665
705
}
666
706
667
- // A compiler error occurred, treat everything that follows as part of the error.
668
- if (line .startsWith ("An exception has occurred in the compiler" )) {
669
- buffer = new StringBuilder ();
670
-
671
- while (line != null ) {
672
- buffer .append (line );
673
- buffer .append (EOL );
674
- line = input .readLine ();
675
- }
676
-
677
- errors .add (new CompilerMessage (buffer .toString (), CompilerMessage .Kind .ERROR ));
678
- return errors ;
679
- } else if (line .startsWith ("An annotation processor threw an uncaught exception." )) {
680
- CompilerMessage annotationProcessingError = parseAnnotationProcessorStream (input );
681
- errors .add (annotationProcessingError );
707
+ if (stackTraceLineCount == 0 && STACK_TRACE_FIRST_LINE .matcher (line ).matches ()
708
+ || STACK_TRACE_OTHER_LINE .matcher (line ).matches ()) {
709
+ stackTraceLineCount ++;
710
+ } else {
711
+ stackTraceLineCount = 0 ;
682
712
}
683
713
684
714
// new error block?
@@ -714,21 +744,6 @@ static List<CompilerMessage> parseModernStream(int exitCode, BufferedReader inpu
714
744
}
715
745
}
716
746
717
- private static CompilerMessage parseAnnotationProcessorStream (final BufferedReader input ) throws IOException {
718
- String line = input .readLine ();
719
- final StringBuilder buffer = new StringBuilder ();
720
-
721
- while (line != null ) {
722
- if (!line .startsWith ("Consult the following stack trace for details." )) {
723
- buffer .append (line );
724
- buffer .append (EOL );
725
- }
726
- line = input .readLine ();
727
- }
728
-
729
- return new CompilerMessage (buffer .toString (), CompilerMessage .Kind .ERROR );
730
- }
731
-
732
747
private static boolean isMisc (String line ) {
733
748
return startsWithPrefix (line , MISC_PREFIXES );
734
749
}
0 commit comments