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

GH-30: Handle files that are empty, have an unknown newline, or can't… #33

Merged
merged 1 commit into from
Sep 9, 2020

Conversation

dwalluck
Copy link
Contributor

@dwalluck dwalluck commented Sep 8, 2020

… be parsed

@dwalluck
Copy link
Contributor Author

dwalluck commented Sep 8, 2020

In addition to throwing a special subclass of IOException on empty files as mentioned in GH-30, this handles two other cases: throw a special exception on UNKNOWN newline, and a normal IOException on parse failure of Java code. The existing code failed to check parseResult.isSuccessful() and in this case, a CompilationUnit still gets returned, so files with syntax errors in the Java code were not being caught. I am not really sure what happened to the files in the case where parseResult.isSuccessful() is false but the code continues past this.

I understand that the Mojo already has access to the file path, so it may not be necessary to store the Path in the exception. However, using separate exceptions allows us to handle different cases easier (e.g., we print a warning instead of failing in two of the three cases).

Copy link
Member

@ctubbsii ctubbsii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR, @dwalluck
I think these changes are fundamentally good, but I think the code in the PR could be polished up a bit. If you want, I can do the polishing myself, but I made a few suggestions, if you want to do it and update your PR.

@ctubbsii ctubbsii added this to the 1.5.0 milestone Sep 9, 2020
@dwalluck dwalluck force-pushed the GH-30 branch 3 times, most recently from 2a65c44 to b211c8f Compare September 9, 2020 02:58
@dwalluck
Copy link
Contributor Author

dwalluck commented Sep 9, 2020

Thanks for the PR, @dwalluck
I think these changes are fundamentally good, but I think the code in the PR could be polished up a bit. If you want, I can do the polishing myself, but I made a few suggestions, if you want to do it and update your PR.

I think I made all requested changes. Please check. I have added to the test cases an additional check which checks the exception message, to verify that the exception message is no longer null.

ctubbsii added a commit that referenced this pull request Sep 9, 2020
* Consolidate exceptions
* Fail at end, regardless of the exception type
* Add invalid file and missing file test cases
@ctubbsii ctubbsii merged commit f23ffba into revelc:main Sep 9, 2020
@ctubbsii
Copy link
Member

ctubbsii commented Sep 9, 2020

@dwalluck Thanks for the PR. I merged your changes, then added some of my own modifications on top of them, that I liked better.

The one thing I didn't keep is the skipping of the files with errors. After reviewing your changes in depth, I decided it would be better to go ahead and fail at the end, if it saw any of these failure cases as well. If it is necessary to allow the code to ignore such failures, we can add a configuration options to ignore failures, and to exit normally from the plugin execution. This is aligned with what other plugins do, such as maven-surefire-plugin. Combined with the existing functionality to add excludes, I think that should suffice for all use cases.

Let me know what you think, and whether you'd be interested in contributing the extra configuration option to ignore failures, or if I should do it, or if you have a different opinion entirely. Thanks.

@dwalluck
Copy link
Contributor Author

dwalluck commented Sep 9, 2020

Let me know what you think, and whether you'd be interested in contributing the extra configuration option to ignore failures, or if I should do it, or if you have a different opinion entirely. Thanks.

When you combine this with a general excludes option that allows you to exclude files (maybe for some reason you don't wish to run it on a certain file, say, if it was copied from another codebase, etc.), then it makes sense.

The problem I see is that an empty Java file and a one line file is legal Java code and doesn't cause a compiler error. In the case of impsort, if there are no imports, then there's nothing for it to do and no reason why it should fail.

My personal opinion is that if the compiler itself accepts a file and there's nothing for impsort to do (say, if isSorted() is true), then it should at most be a warning and not fail the build.

I agree that in cases where impsort is prevented from doing its job, because newlines are inconsistent, then it makes sense to fail.

@ctubbsii
Copy link
Member

ctubbsii commented Sep 9, 2020

My personal opinion is that if the compiler itself accepts a file and there's nothing for impsort to do (say, if isSorted() is true), then it should at most be a warning and not fail the build.

I agree with this... mostly. But, there are limits. For example, the parser library we use isn't perfect... and this plugin can have also have its own issues if the file isn't well-formatted first (as in #1). So, not all files accepted by the compiler are expected to work in this plugin. It expects some sanely-formatted files first, as a prerequisite.

Also, some of these situations may occur because of issues where something unexpected is occurring, and not because the file is actually intended to be zero-length or be one-line without a line ending (which are pretty unusual circumstances, after all). Some possibilities include: a bad mount point, an incorrect symlink, a file locked by an editor, etc.

Always failing on these files unless they are added explicitly to an excludes list I think is reasonable behavior, given the rarity of which these situations are expected to occur, and because they are far more likely indicative of an underlying problem, IMO, rather than an intended zero-length or one-line Java file.

I agree that in cases where impsort is prevented from doing its job, because newlines are inconsistent, then it makes sense to fail.

I like this way of presenting the problem. I'll get some dinner, and think it over a bit, and take another pass later today, or tomorrow.

@dwalluck
Copy link
Contributor Author

dwalluck commented Sep 9, 2020

I like this way of presenting the problem. I'll get some dinner, and think it over a bit, and take another pass later today, or tomorrow.

I also think that if you implement a general excludes option (as you said, most plugins have this option), then you may not need a separate option to ignore failures, since a user could just add that file to the excludes list in this case, right?

@ctubbsii
Copy link
Member

I also think that if you implement a general excludes option (as you said, most plugins have this option), then you may not need a separate option to ignore failures, since a user could just add that file to the excludes list in this case, right?

Right, but we already have that excludes option here. I assumed, based on this conversation, that you were looking for more than that.

@dwalluck
Copy link
Contributor Author

Right, but we already have that excludes option here. I assumed, based on this conversation, that you were looking for more than that.

It depends whether you think the existing option is good enough or there should be a separate one.

@ctubbsii
Copy link
Member

Right, but we already have that excludes option here. I assumed, based on this conversation, that you were looking for more than that.

It depends whether you think the existing option is good enough or there should be a separate one.

What would you want a separate one to do? Exclude by category (empty, unknown line ending, etc.), or something else? I'm not sure what the "good enough" criteria is here. Personally, I think the current one is good enough... but maybe I'm missing a use case to consider.

@dwalluck
Copy link
Contributor Author

What would you want a separate one to do? Exclude by category (empty, unknown line ending, etc.), or something else? I'm not sure what the "good enough" criteria is here. Personally, I think the current one is good enough... but maybe I'm missing a use case to consider.

The excludes option is probably "good enough" already. If you wanted to improve it, I think I would add separate boolean options for each case such as <failOnEmptyFile>true</failOnEmptyFile>.

@ctubbsii
Copy link
Member

@dwalluck I made some changes in #34 that I think which covers some of the stuff we've discussed here. Specifically, it skips empty files, and only throws an exception on UNKNOWN line endings if the line ending was configured to KEEP. I changed the way it read in the lines to the array, so it wouldn't hit the NPE with UNKNOWN by trying to split the buffer on a null regex, but instead would use Java's built-in Scanner utility to read lines. Let me know on that PR what you think.

@ctubbsii
Copy link
Member

ctubbsii commented Oct 6, 2020

I discovered a problem with checking isSuccessful and reported it upstream at javaparser/javaparser#2820

I have a workaround in progress.

@dwalluck dwalluck deleted the GH-30 branch October 6, 2020 19:03
ctubbsii added a commit that referenced this pull request Oct 6, 2020
* Format code
* Bump versions
* Workaround javaparser/javaparser#2820 introduced in #33 by explicitly
  checking for the problem message and ignoring it (while printing other
  problems before throwing an exception)
@ctubbsii
Copy link
Member

ctubbsii commented Oct 6, 2020

Worked around the above issue in 340d7e2

@ctubbsii
Copy link
Member

ctubbsii commented Oct 6, 2020

The above workaround was removed and properly fixed by adding a configurable compiler compliance level #37

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.

2 participants