New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue#1395 : Dump on error fix #3406
Conversation
docs/manual/creating-a-checker.tex
Outdated
@@ -1783,6 +1783,10 @@ | |||
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 the stack trace of the program when the | |||
Checker Framework encounters an error or warning. The option also requires a | |||
boolean parameter to enables its functionality (e.g. \code{-AdumpOnErrors=true}). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The boolean shouldn't be required, see the other boolean flags above. Just passing -AdumOnErrors
should be equal to -AdumOnErrors=true
. The user could turn off the flag using -AdumOnErrors=false
.
if (dumpOnErrors) { | ||
for (StackTraceElement elem : trace) { | ||
String msg = "\tat " + elem; | ||
message(Diagnostic.Kind.NOTE, msg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't want individual messages for each element. Build up one string, including line breaks, and issue one NOTE.
framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java
Show resolved
Hide resolved
Earlier reviews aditya3434#2 |
docs/manual/creating-a-checker.tex
Outdated
@@ -1783,6 +1783,9 @@ | |||
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 the stack trace of the program when the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can remove the of the program
and shorten to output a stack trace when reporting errors or warnings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have updated the documentation in my latest commit.
@@ -315,6 +316,10 @@ | |||
// org.checkerframework.framework.util.typeinference.DefaultTypeArgumentInference | |||
"showInferenceSteps", | |||
|
|||
// Output stack trace when checker encounters errors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the short message I proposed for the manual.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have used the short message in my latest commit.
} | ||
|
||
/** | ||
* Constructor method for checker message if stack trace needs to be stored. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't say constructor message
. The same Create a new CheckerMessage.
as for the other constructor is fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, there are no calls of the constructor without a trace, so why have two constructors?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have updated the summary and removed the first redundant constructor from BaseTypeChecker.
framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java
Show resolved
Hide resolved
framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java
Show resolved
Hide resolved
*/ | ||
private void printStackTrace(StackTraceElement[] trace) { | ||
boolean dumpOnErrors = | ||
getOptions().containsKey("dumpOnErrors") && getBooleanOption("dumpOnErrors", true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this just be getBooleanOption("dumpOnErrors")
? That method already checks whether the option is given and false should be the default, shouldn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I originally tried getBooleanOption("dumpOnErrors", false)
, however it returns false whenever no boolean argument is given. getBooleanOption("dumpOnErrors", true)
works for the most part but returns true even if the dumpOnErrors
option is not provided. To prevent that, I used the getOptions().containsKey("dumpOnErrors")
to check whether the dumpOnErrors option is given.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a bit odd, looking at
checker-framework/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java
Line 1589 in 3498970
if (value == null) { |
Can you investigate why this doesn't work as specified?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we write dumpOnErrors
without a boolean argument, the value
variable in the getBooleanOption()
method would be null. Hence, the function would return the default value which, if we used getBooleanOption("dumpOnErrors", false)
would be false. So the stack trace won't be printed if we don't give the boolean value true
. If we use getBooleanOption("dumpOnErrors", true)
, then we don't need a boolean argument to print the stack trace, however, then it would print the stack trace even if dumpOnErrors
is not provided because value
will be null, and it would return the default value which is true
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is simply hasOption("dumpOnErrors")
enough? Then you don't need to introduce a local variable for this.
In a separate PR, can you look into what getBooleanOption
is doing wrong? It is hardly used, so we should discuss what the correct behavior is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hasOption("dumpOnErrors")
is the same as getOptions().containtsKey("dumpOnErrors")
. If we give the option -AdumpOnErrors=false
, hasOption("dumpOnErrors")
will return true. Hence, we cannot use this directly. I have replaced getOptions().containtsKey("dumpOnErrors")
with hasOption("dumpOnErrors")
.
boolean dumpOnErrors = | ||
getOptions().containsKey("dumpOnErrors") && getBooleanOption("dumpOnErrors", true); | ||
if (dumpOnErrors) { | ||
String msg = new String(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't build up with just a String! In particular that initial new String()
is very ugly.
Use a StringBuilder or a StringJoiner.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have used a StringBuilder to build the stack trace and print it as a note in my latest commit.
@@ -599,6 +600,8 @@ private void printStoredMessages(CompilationUnitTree unit) { | |||
final String message; | |||
/** The source code that the message is about. */ | |||
final @InternedDistinct Tree source; | |||
/** Stores the stack trace till the point the checker encounters an error. */ | |||
final StackTraceElement @Nullable [] trace; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the field @Nullable
? Same for the trace
parameter that sets the field.
Thread.currentThread().getStackTrace()
returns something non-null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the IDE added it automatically when I initialized it. I have removed the annotation since it was, as you said, redundant.
framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java
Show resolved
Hide resolved
framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java
Show resolved
Hide resolved
*/ | ||
private void printStackTrace(StackTraceElement[] trace) { | ||
boolean dumpOnErrors = | ||
getOptions().containsKey("dumpOnErrors") && getBooleanOption("dumpOnErrors", true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a bit odd, looking at
checker-framework/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java
Line 1589 in 3498970
if (value == null) { |
Can you investigate why this doesn't work as specified?
@@ -599,6 +600,8 @@ private void printStoredMessages(CompilationUnitTree unit) { | |||
final String message; | |||
/** The source code that the message is about. */ | |||
final @InternedDistinct Tree source; | |||
/** Stores the stack trace till the point the checker encounters an error. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the stack trace when it encountered an error, so this should be something like The stack trace when the message is created.
Also change the parameter documentation to the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have changed the field and parameter description in my latest commit.
} | ||
|
||
/** | ||
* printOrStoreMessage method with an added stack trace argument. The stack trace is printed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like for other overloaded methods, start out with the normal description of what the method is for and then describe the differences.
Also, @see
cross-references can be useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have updated the documentation in my latest commit.
Tree source, | ||
CompilationUnitTree root, | ||
StackTraceElement[] trace) { | ||
// Not calling printOrStoreMessage(kind, message, source, root) since the error message |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That comment is out-of-date - you would now create an infinite loop, so this question no longer arises.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have deleted the comment in my latest commit.
*/ | ||
private void printStackTrace(StackTraceElement[] trace) { | ||
boolean dumpOnErrors = | ||
getOptions().containsKey("dumpOnErrors") && getBooleanOption("dumpOnErrors", true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is simply hasOption("dumpOnErrors")
enough? Then you don't need to introduce a local variable for this.
In a separate PR, can you look into what getBooleanOption
is doing wrong? It is hardly used, so we should discuss what the correct behavior is.
Fix for issue #1395 (dump-on-error). Compound checkers such as nullness and index checkers were not giving adequate stack trace to pin-point where the error in the code had occurred. This was because in BaseTypeChecker, errors due to checkers with subcheckers were stored in CheckerMessage but those without were printed right away giving a correct stack trace. This storage caused the stack trace to unwind and take a different path. Since, all errors were stored in the same place, they gave the same stack trace when the -doe option is used. To fix this problem, I added a CheckerMessage constructor to store the stack trace when the error occurred. Then, I added a method to print this stored stack trace for all the stored errors. The code gives the correct stack trace when used with the '-AdumpOnErrors' compiler option.
Fixes #1395.