6565import  java .util .Properties ;
6666import  java .util .StringTokenizer ;
6767import  java .util .concurrent .ConcurrentLinkedDeque ;
68+ import  java .util .regex .Pattern ;
6869
6970import  org .codehaus .plexus .compiler .AbstractCompiler ;
7071import  org .codehaus .plexus .compiler .CompilerConfiguration ;
@@ -627,6 +628,16 @@ private static CompilerResult compileInProcess0(Class<?> javacClass, String[] ar
627628 return  new  CompilerResult (success , messages );
628629 }
629630
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+ 
630641 /** 
631642 * Parse the output from the compiler into a list of CompilerMessage objects 
632643 * 
@@ -643,6 +654,7 @@ static List<CompilerMessage> parseModernStream(int exitCode, BufferedReader inpu
643654 StringBuilder  buffer  = new  StringBuilder ();
644655
645656 boolean  hasPointer  = false ;
657+  int  stackTraceLineCount  = 0 ;
646658
647659 while  (true ) {
648660 line  = input .readLine ();
@@ -659,26 +671,44 @@ static List<CompilerMessage> parseModernStream(int exitCode, BufferedReader inpu
659671 } else  if  (hasPointer ) {
660672 // A compiler message remains in buffer at end of parse stream 
661673 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 ));
662702 }
663703 }
664704 return  errors ;
665705 }
666706
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 ;
682712 }
683713
684714 // new error block? 
@@ -714,21 +744,6 @@ static List<CompilerMessage> parseModernStream(int exitCode, BufferedReader inpu
714744 }
715745 }
716746
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- 
732747 private  static  boolean  isMisc (String  line ) {
733748 return  startsWithPrefix (line , MISC_PREFIXES );
734749 }
0 commit comments