-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Enable error-prone static analysis checks #961
Conversation
Work on this PR has been postponed until google/error-prone#685 is resolved. |
google/error-prone#685 has been resolved, but it hasn't had time to make it into an error-prone release yet, so I'll see if I can use an earlier version of error-prone. |
Related to #358 ... and related to the implementation it might actually close that issue. I don't really care which library is chosen to perform this checking ... at this point FindBugs (and JSR-305 itself) seems dead. Note that JSR-305 has been implemented quite a few times. This is something I intend to ask the JCP executive committee at JavaOne this year. ErrorProne and SpotBugs both support the JSR-305 proposal, so picking ErrorProne is probably a good decision. There was also a good discussion in JUnit Pioneer about this (junit-pioneer/junit-pioneer#33) and I think that we'll probably just follow the JUnit team's lead. |
@smoyer64 it seems spotbugs is coming along nicely, and should soon be poised to be a full replacement for findbugs. Findbugs/spotbugs serves a similar, but different purpose as well - so including both might be useful to consider ( along with fb-contrib, find-sec-bugs extensions). |
@talios - I'm a big fan of find-sec-bugs so I should have specifically mentioned that plugin package. The fb-contrib plugins also look great and I'm thinking I should add these to my parent POM. |
@talios I am actually considering Spotbugs as well. I think it or FindBugs would work well with error-prone, since error-prone itself doesn't catch everything that FindBugs does, and vice-versa. @smoyer64 For null checking, I'll look into the Checker Framework. Its null checking is exhaustive (which is what makes it a formal verification tool as opposed to just a static analysis tool), whereas FindBugs' null checking isn't. Also, I'm not sure if either of you have seen |
Oh that's a bummer; error-prone doesn't seem to work yet on JDK 9, so Travis is complaining about it. I'll see if I can find a way in the meantime of disabling error-prone when running on JDK 9. |
@sbrannen @marcphilipp I've made some comments in my recent commits asking about certain things related to error-prone which I'd quite like both your feedback on. Would you mind taking a look? |
9d5c483
to
ceb3d4d
Compare
@sbrannen @marcphilipp FYI, the reason If you'd like me to revert these changes because e.g. they're too invasive, please do let me know. |
I'm not a fan of MethodsCanBeStatic to be honest. The description of InconsistentOverloads is very... ehm... concise. What does it try to accomplish? Which rule caused you to reorder parameters of a lot of methods? |
@marcphilipp I agree that the description of InconsistentOverloads is... concise. 😉 IIRC, it reports warnings when two or more methods with the same name (overloads) don't start with the exact same sequence of parameters. For example, this passes without warning because the two overloads' common subset of parameters ( public m(int a, double b, long c) {}
public m(int a, double b, long c, Object d) {} However this example fails because for the second overload, parameter public m(int a, double b, long c) {}
public m(int a, double b, Object d, long c) {} So to answer your 2nd question, it was the InconsistentOverloads rule which prompted me to reorder parameters in a lot of methods. |
Okey dokey! Would you like me to revert the changes I made to satisfy that rule? 😃 |
Would you also like me to revert the changes I made for InconsistentOverloads? |
Note, I've just rebased this PR on master and pushed two new commits - one a filename cleanup commit (which was caught by error-prone), the other an attempt to enable error-prone's "Immutable" check. |
The "Immutable" check fails on JDK 9, just like my earlier attempt with the "Var" check. So I've pushed a new commit which disables all checks that depend on error-prone annotations. |
@sbrannen I understand that @marcphilipp is on holiday, so I wondered if you could confirm for me in his stead if I should disable and revert the MethodsCanBeStatic and InconsistentOverloads rules discussed above? |
I'm actually also on vacation and therefore haven't had a chance to look at this in detail yet. But I'll see if I can get to it within the next week or so; otherwise, one of us will get back to you after our vacations. 😉 |
Oops! Pardon me. For some reason I thought you never went on holiday or finished early, which was why I asked for your confirmation specifically. 😜 Tell you what, I'll go and disable both of those rules as soon as I have the time, since they don't seem to buy much, and I believe disabling both of them would make reviewing this PR much easier. After all, they can always be re-enabled at a later point in time if desired. |
Okay, those two rules and their respective changes have been reverted. |
/* no-op */ | ||
} | ||
///CLOVER:ON | ||
|
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.
Would you mind moving all of theses private constructors in Assert*
classes to a separate PR?
We can then merge that new PR immediately.
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.
Certainly. Should be done and ready for merging over at #1027.
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.
@sbrannen Ah, I remember now why I added these private constructors in this PR rather than a separate one in the first place. It's because error-prone purposely fails to compile whenever classes like Assert*
don't have associated private constructors.
The error message that error-prone reports for me is as follows:
C:\Users\Jonathan\dev\Java\IntelliJ Projects\junit5\junit-jupiter-api\src\main\java\org\junit\jupiter\api\AssertFalse.java:24: warning: [PrivateConstructorForUtilityClass] Utility classes (only static members) are not designed to be instantiated and should be made noninstantiable with a default constructor.
class AssertFalse {
^
(see http://errorprone.info/bugpattern/PrivateConstructorForUtilityClass)
Did you mean to remove this line?
Consequently, Travis CI won't go green until #1027 gets merged into master and I can rebase this PR on top of 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.
#1027 has been merged.
So feel free to rebase on master
at your leisure.
build.gradle
Outdated
@@ -9,10 +9,13 @@ buildscript { | |||
} | |||
dependencies { | |||
classpath 'com.diffplug.spotless:spotless-plugin-gradle:3.4.1' | |||
classpath 'com.github.ben-manes:gradle-versions-plugin:0.15.0' |
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 just moved that declaration in e6825ea.
So you can rebase on master
at your leisure. 😉
build.gradle
Outdated
// disable, similarly to how we specify "-Xlint" flags above. | ||
// Do we want to customise exactly which checks error-prone should run? Or are we happy to just | ||
// accept the default checks that each new release brings, explictly excluding the ones we dislike? | ||
if (JavaVersion.current() == JavaVersion.VERSION_1_8 && subproj.name != 'documentation') { |
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'd say, for now, we can "just accept the default checks that each new release brings, explictly excluding the ones we dislike."
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.
Great, thanks for clarifying things for me @sbrannen! I'll work on reverting this comment now.
} | ||
else { | ||
return String.valueOf(obj); | ||
} |
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 seems to be an unrelated "fix".
Can you please move this to a separate PR outlining the rationale for the change?
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.
Can you please move this to a separate PR outlining the rationale for the change?
See https://github.com/junit-team/junit5/pull/961/files#r134096347 for the rationale. :)
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.
Done! 👍
static boolean floatsAreEqual(float value1, float value2) { | ||
return Float.floatToIntBits(value1) == Float.floatToIntBits(value2); | ||
} | ||
|
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 did you move this method?
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 moved it because, before I added "-Xep:UngroupedOverloads:OFF" to the build.gradle
file, error-prone reported that methods like this one were not 'grouped' together with methods of the same name, potentially causing confusion for future maintainers.
I ultimately added "-Xep:UngroupedOverloads:OFF" to the build.gradle
because the corresponding rule produced a lot of churn for little gain, but as I was reverting the changes I made initially to satisfy the rule, I thought that moving all the floatsAreEqual()
methods together made a great deal of sense, so I decided to keep it.
If you want me to move it back to where it was, or to put this change in a new PR, please let me know!
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.
You can leave it "as is" for the time being.
@@ -128,7 +128,7 @@ void failWithNullStringAndThrowable() { | |||
@Test | |||
void failUsableAsAnExpression() { | |||
// @formatter:off | |||
long count = Collections.emptySet().stream() | |||
long count = Stream.empty() | |||
.peek(element -> fail("peek should never be called")) | |||
.filter(element -> fail("filter should never be called", new Throwable("cause"))) | |||
.map(element -> fail(new Throwable("map should never be called"))) |
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.
Addressed in db33cc1.
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.
Ta! I'll revert this particular change then.
"Too few test descriptors in classpath"); | ||
assertThat(engineDescriptor.getDescendants().size()) // | ||
.as("Too few test descriptors in classpath") // | ||
.isGreaterThan(150); | ||
|
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.
Addressed in db33cc1.
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.
Thanks again! Reverting this change...
@@ -49,7 +49,7 @@ void privateInnerClassEvaluatesToFalse() { | |||
|
|||
} | |||
|
|||
//class name must not end with 'Tests', otherwise it would be picked up by the suite | |||
// Class name must not end with 'Tests', otherwise it would be picked up by the suite | |||
class ClassWithInnerClasses { |
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.
Addressed in db33cc1.
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.
👍
@@ -50,7 +50,7 @@ void privateNestedClassEvaluatesToFalse() { | |||
|
|||
} | |||
|
|||
//class name must not end with 'Tests', otherwise it would be picked up by the suite | |||
// Class name must not end with 'Tests', otherwise it would be picked up by the suite |
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.
Addressed in db33cc1.
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.
👍
@@ -13,7 +13,7 @@ | |||
class FailAfterAllHelper { | |||
|
|||
static void fail() { | |||
//hack: use this blacklisted exception to fail the build, all others would be swallowed... | |||
// hack: use this blacklisted exception to fail the build, all others would be swallowed... | |||
throw new OutOfMemoryError("a postcondition was violated"); | |||
} |
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.
Addressed in db33cc1.
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.
👍
No worries. 😉
Sounds good. FYI: I also pushed some of your recommended changes in various "Polishing" commits and requested that you move some of your additional unrelated changes to a separate. So the results of those two actions will also make this PR easier to swallow. |
Great! Sounds very reasonable to me, so I'll happily create separate PRs for the corresponding comments and do whatever else needs to be done to cleanup this PR. I intend to process your comments above as soon as I can, but I'm currently going through a busy time IRL, so it might take me a few days to process everything. |
Sure. No worries, no hurry. But... it'd be nice to have the polishing commits in place before RC3. 😉 |
future release of error-prone anyway. Also, disable use of error-prone in `./gradlew compile[Test]Java` and introduce experimental tasks for compiling java sources with error-prone.
…h problems that I'm struggling to resolve...)
`compileJavaWithErrorProne` works now, but problems still persist with `compileTestJavaWithErrorProne`.
93cb69f
to
31add43
Compare
@marcphilipp @JLLeitschuh Thank you very much for your thoughts on this! I've found that making (FYI, I've been busy with a new job, which is why it took me so long to get back to both of you. I hope you'll accept my apologies.) |
...but it seems I have encountered yet another stumbling block. Travis, AppVeyor and my local setup seem to complain that they can't find any Java 9 related classes when compiling subproject if (!project.name.endsWith('-java-9')
// error-prone doesn't work with Java 9 sources yet:
// https://github.com/google/error-prone/issues/448
&& subproj.name != 'documentation') {
apply plugin: 'net.ltgt.errorprone-base'
[...]
} Do y'all have any further thoughts on this? |
Wait until errorprone supports Java 9? ;) Mh, why are checking |
Good catch @sormuras! Sadly, it hasn't worked. :,(
;) I'll persevere with this PR for a bit longer, methinks. This camel can carry more straws on its back. ;) (I'll just leave it for another day now, as it's getting late here in the UK and my mind is dozing off.) If you or @marcphilipp have any further thoughts that may allow me to get unstuck again, I would be immensely grateful. |
It's getting prohibitively difficult for me to continuously rebase this PR over master, and the size of this PR has reached a point where I can't easily debug problems, so I'm closing it with the intention of re-opening it in a new PR. |
Prior to this commit, AssertionUtils.toString(Object) printed an array via the array's toString() method which resulted in non-user-friendly output. This commit addresses this issue by printing arrays using Arrays.toString(), which produces human readable output. This is a prerequisite for junit-team#961. Issue: junit-team#1030
Overview
Following issue #955, this is a work-in-progress PR to introduce error-prone checks to JUnit 5.
Feedback is welcome!
I hereby agree to the terms of the JUnit Contributor License Agreement.
Definition of Done
@API
annotations