Skip to content
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

Merged
merged 43 commits into from Jul 31, 2020

Conversation

aditya3434
Copy link
Contributor

@aditya3434 aditya3434 commented Jun 27, 2020

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.

@aditya3434 aditya3434 requested a review from wmdietl June 27, 2020 09:14
@aditya3434 aditya3434 assigned wmdietl and aditya3434 and unassigned aditya3434 Jun 27, 2020
@@ -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}).
Copy link
Member

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);
Copy link
Member

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.

@wmdietl
Copy link
Member

wmdietl commented Jul 1, 2020

Earlier reviews aditya3434#2

@smillst smillst assigned aditya3434 and unassigned wmdietl Jul 2, 2020
@aditya3434 aditya3434 assigned wmdietl and unassigned aditya3434 Jul 10, 2020
@@ -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
Copy link
Member

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.

Copy link
Contributor Author

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
Copy link
Member

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.

Copy link
Contributor Author

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.
Copy link
Member

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.

Copy link
Member

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?

Copy link
Contributor Author

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.

*/
private void printStackTrace(StackTraceElement[] trace) {
boolean dumpOnErrors =
getOptions().containsKey("dumpOnErrors") && getBooleanOption("dumpOnErrors", true);
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Member

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

I wouldn't expect that behavior.
Can you investigate why this doesn't work as specified?

Copy link
Contributor Author

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.

Copy link
Member

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.

Copy link
Contributor Author

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();
Copy link
Member

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.

Copy link
Contributor Author

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.

@wmdietl wmdietl assigned aditya3434 and unassigned wmdietl Jul 20, 2020
@@ -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;
Copy link
Member

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.

Copy link
Contributor Author

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.

*/
private void printStackTrace(StackTraceElement[] trace) {
boolean dumpOnErrors =
getOptions().containsKey("dumpOnErrors") && getBooleanOption("dumpOnErrors", true);
Copy link
Member

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

I wouldn't expect that behavior.
Can you investigate why this doesn't work as specified?

@aditya3434 aditya3434 assigned wmdietl and unassigned aditya3434 Jul 24, 2020
@@ -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. */
Copy link
Member

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.

Copy link
Contributor Author

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
Copy link
Member

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.

Copy link
Contributor Author

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
Copy link
Member

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.

Copy link
Contributor Author

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);
Copy link
Member

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.

@wmdietl wmdietl assigned aditya3434 and unassigned wmdietl Jul 29, 2020
@aditya3434 aditya3434 assigned wmdietl and unassigned aditya3434 Jul 30, 2020
@wmdietl wmdietl merged commit e8be209 into typetools:master Jul 31, 2020
@aditya3434 aditya3434 deleted the 1395-dump-on-error-fix branch July 31, 2020 06:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement Dump-on-Error alternative
2 participants