From e8be2098f2c39a2d7830e6b7fc64af081fe95d2f Mon Sep 17 00:00:00 2001 From: aditya3434 <56246494+aditya3434@users.noreply.github.com> Date: Fri, 31 Jul 2020 05:58:13 +0530 Subject: [PATCH] Add dump-on-error option (Fixes #1395) (#3406) --- docs/manual/creating-a-checker.tex | 2 + docs/manual/introduction.tex | 1 + .../common/basetype/BaseTypeChecker.java | 22 ++++++---- .../framework/source/SourceChecker.java | 44 ++++++++++++++++++- 4 files changed, 60 insertions(+), 9 deletions(-) diff --git a/docs/manual/creating-a-checker.tex b/docs/manual/creating-a-checker.tex index 7c66d20a5c2..1c189236d05 100644 --- a/docs/manual/creating-a-checker.tex +++ b/docs/manual/creating-a-checker.tex @@ -1783,6 +1783,8 @@ already reported the bug, and you want to continue using the checker on a large codebase without being inundated in stack traces. +\item \code{-AdumpOnErrors}: Outputs a stack trace when reporting errors or warnings. + \end{itemize} diff --git a/docs/manual/introduction.tex b/docs/manual/introduction.tex index b80b9ca89b8..9bcb29d4905 100644 --- a/docs/manual/introduction.tex +++ b/docs/manual/introduction.tex @@ -746,6 +746,7 @@ \<-AprintAllQualifiers>, \<-AprintVerboseGenerics>, \<-Anomsgtext> + \<-AdumpOnErrors> Amount of detail in messages; see Section~\ref{creating-debugging-options-detail}. \item diff --git a/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeChecker.java b/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeChecker.java index 7d56101f9fe..211106a3e1d 100644 --- a/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeChecker.java +++ b/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeChecker.java @@ -568,10 +568,11 @@ protected void warnUnneededSuppressions() { protected void printOrStoreMessage( Diagnostic.Kind kind, String message, Tree source, CompilationUnitTree root) { assert this.currentRoot == root; + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); if (messageStore == null) { - super.printOrStoreMessage(kind, message, source, root); + super.printOrStoreMessage(kind, message, source, root, trace); } else { - CheckerMessage checkerMessage = new CheckerMessage(kind, message, source, this); + CheckerMessage checkerMessage = new CheckerMessage(kind, message, source, this, trace); messageStore.add(checkerMessage); } } @@ -586,7 +587,7 @@ protected void printOrStoreMessage( private void printStoredMessages(CompilationUnitTree unit) { if (messageStore != null) { for (CheckerMessage msg : messageStore) { - super.printOrStoreMessage(msg.kind, msg.message, msg.source, unit); + super.printOrStoreMessage(msg.kind, msg.message, msg.source, unit, msg.trace); } } } @@ -599,6 +600,8 @@ private static class CheckerMessage { final String message; /** The source code that the message is about. */ final @InternedDistinct Tree source; + /** Stores the stack trace when the message is created. */ + final StackTraceElement[] trace; /** * The checker that issued this message. The compound checker that depends on this checker @@ -609,20 +612,23 @@ private static class CheckerMessage { /** * Create a new CheckerMessage. * - * @param kind the severity of the message - * @param message the text of the message - * @param source the source code that the message is about - * @param checker the checker that issued the message. + * @param kind kind of diagnostic, for example, error or warning + * @param message error message that needs to be printed + * @param source tree element causing the error + * @param checker the type-checker in use + * @param trace the stack trace when the message is created */ private CheckerMessage( Diagnostic.Kind kind, String message, @FindDistinct Tree source, - @FindDistinct BaseTypeChecker checker) { + @FindDistinct BaseTypeChecker checker, + StackTraceElement[] trace) { this.kind = kind; this.message = message; this.source = source; this.checker = checker; + this.trace = trace; } @Override diff --git a/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java b/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java index 2ff0cde379b..ece60f75fb4 100644 --- a/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java +++ b/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java @@ -52,6 +52,7 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; +import javax.tools.Diagnostic; import javax.tools.Diagnostic.Kind; import org.checkerframework.checker.compilermsgs.qual.CompilerMessageKey; import org.checkerframework.checker.interning.qual.InternedDistinct; @@ -317,6 +318,10 @@ // org.checkerframework.framework.util.typeinference.DefaultTypeArgumentInference "showInferenceSteps", + // Output a stack trace when reporting errors or warnings + // org.checkerframework.common.basetype.SourceChecker.printStackTrace() + "dumpOnErrors", + /// Visualizing the CFG // Implemented in the wrapper rather than this file, but worth noting here. @@ -1073,7 +1078,7 @@ private void printMessage(String msg) { * * @param kind the kind of message to print * @param message the message text - * @param source the souce code position of the diagnostic message + * @param source the source code position of the diagnostic message * @param root the compilation unit */ protected void printOrStoreMessage( @@ -1081,7 +1086,44 @@ protected void printOrStoreMessage( String message, Tree source, CompilationUnitTree root) { + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + printOrStoreMessage(kind, message, source, root, trace); + } + + /** + * Stores all messages and sorts them by location before outputting them for compound checkers. + * This method is overloaded with an additional stack trace argument. The stack trace is printed + * when the dumpOnErrors option is enabled. + * + * @param kind the kind of message to print + * @param message the message text + * @param source the source code position of the diagnostic message + * @param root the compilation unit + * @param trace the stack trace where the checker encountered an error + */ + protected void printOrStoreMessage( + javax.tools.Diagnostic.Kind kind, + String message, + Tree source, + CompilationUnitTree root, + StackTraceElement[] trace) { Trees.instance(processingEnv).printMessage(kind, message, source, root); + printStackTrace(trace); + } + + /** + * Output the given stack trace if the "dumpOnErrors" option is enabled. + * + * @param trace stack trace when the checker encountered a warning/error + */ + private void printStackTrace(StackTraceElement[] trace) { + if (hasOption("dumpOnErrors")) { + StringBuilder msg = new StringBuilder(); + for (StackTraceElement elem : trace) { + msg.append("\tat " + elem + "\n"); + } + message(Diagnostic.Kind.NOTE, msg.toString()); + } } ///////////////////////////////////////////////////////////////////////////