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

Add checkerframework and errorprone #2941

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

juherr
Copy link
Member

@juherr juherr commented Jul 31, 2023

Try checkerframework and errorprone

@juherr
Copy link
Member Author

juherr commented Jul 31, 2023

@vlsi Any feedback about the 2 tools and how I added them in the build (even if I was inspired by what you did on pg-driver)?

@krmahadevan WDYT? They highlight a lot of minor issues but some potential problems too.

@krmahadevan
Copy link
Member

@juherr - This is definitely a good addition. I am yet to explore both these tools. I have already seen error prone being used by jhipster when it scaffolds a new project based on my inputs.

Couple of questions:

  • These highlight the problems in our code, but would it prevent TestNG from being used incorrectly by its consumers (especially the ones that use the TestNG apis to provide customised runners etc., ?)
  • The CI has failed, mainly because of the discrepancies in our code, which you also highlighted. So for us to adopt these two tools, I believe we would need to iterate on all the failures and then fix them right ?

@juherr
Copy link
Member Author

juherr commented Jul 31, 2023

Thanks.

These highlight the problems in our code, but would it prevent TestNG from being used incorrectly by its consumers (especially the ones that use the TestNG apis to provide customised runners etc., ?)

As I understand, yes. It provides extra data in bytecode thanks to the annotations.
The drawback is it is adding a new runtime dependency (because the annotations are stored in the bytecode).

The CI has failed, mainly because of the discrepancies in our code, which you also highlighted. So for us to adopt these two tools, I believe we would need to iterate on all the failures and then fix them right ?

To be honest, I hoped there were a bit less. That's why I sent the draft before fixing them all.

@vlsi
Copy link
Contributor

vlsi commented Jul 31, 2023

"nullability" is not trivial, so it might take some time to properly annotate and identify nullable types.
The general advice is assume "everything is not nullable by default" (==almost never put @NotNull), and annotate @Nullable where null values are allowed.

Comment on lines 11 to 12
plugins.withId("org.checkerframework") {
configure<CheckerFrameworkExtension> {
Copy link
Contributor

Choose a reason for hiding this comment

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

plugins { id("org.checkerframework") } adds checkerframework plugin, so plugins.withId(..) is not needed here.

Something like checkerframework {...} should do.

@@ -1750,7 +1765,8 @@ public static void assertEquals(Iterable<?> actual, Iterable<?> expected, String
* @param expected the expected value
* @param message the assertion error message
*/
public static void assertEquals(Object[] actual, Object[] expected, String message) {
public static void assertEquals(
@Nullable Object[] actual, @Nullable Object[] expected, @Nullable String message) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe it should be @Nullable Object @Nullable [] actual: nullable array of nullable elements

@@ -17,7 +19,7 @@ public interface IObjectFactory2 extends ITestObjectFactory {
* @return - The newly created object.
*/
@Deprecated
default Object newInstance(Class<?> cls) {
default Object newInstance(@NonNull Class<?> cls) {
Copy link
Contributor

Choose a reason for hiding this comment

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

@vlsi
Copy link
Contributor

vlsi commented Jul 31, 2023

In my experience, checkerframework nullability verification takes time, so I tend to activate it only when -PenableCheckerframework parameter is specified. Then checkerframework executes in a single CI job only.

See https://github.com/apache/jmeter/blob/c94db9741f0547235f9a67b1ece40389add6b742/build-logic/build-parameters/build.gradle.kts#L77 , and https://github.com/apache/jmeter/blob/c94db9741f0547235f9a67b1ece40389add6b742/build-logic/verification/src/main/kotlin/build-logic.style.gradle.kts#L42-L43 (conditional activation of .checkerframework.gradle.kts)

@juherr
Copy link
Member Author

juherr commented Jul 31, 2023

Thanks for the feedbacks @vlsi ❤️

@juherr
Copy link
Member Author

juherr commented Aug 7, 2023

Updated according to reviews.

All issues are not fixed yet.

Still 2 gradle issues: not succeeding in using the parameters plugin + not finding the way to merge package-info

@juherr juherr requested a review from vlsi August 7, 2023 07:06
@@ -124,7 +126,7 @@ public static void fail() {
* @param expected the expected value
* @param message the assertion error message
*/
public static void assertEquals(Object actual, Object expected, String message) {
public static void assertEquals(Object actual, Object expected, @Nullable String message) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
public static void assertEquals(Object actual, Object expected, @Nullable String message) {
public static void assertEquals(@Nullable Object actual, @Nullable Object expected, @Nullable String message) {

@@ -761,7 +769,7 @@ public static void assertEquals(double actual, Double expected, String message)
* @param expected the expected value
* @param message the assertion error message
*/
public static void assertEquals(Double actual, Double expected, String message) {
public static void assertEquals(Double actual, Double expected, @Nullable String message) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
public static void assertEquals(Double actual, Double expected, @Nullable String message) {
public static void assertEquals(@Nullable Double actual, @Nullable Double expected, @Nullable String message) {

@@ -900,7 +909,7 @@ public static void assertEquals(float actual, Float expected, String message) {
* @param expected the expected value
* @param message the assertion error message
*/
public static void assertEquals(Float actual, Float expected, String message) {
public static void assertEquals(Float actual, Float expected, @Nullable String message) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
public static void assertEquals(Float actual, Float expected, @Nullable String message) {
public static void assertEquals(@Nullable Float actual, @Nullable Float expected, @Nullable String message) {

@@ -1653,7 +1674,7 @@ public static void assertEquals(Collection<?> actual, Collection<?> expected, St
* @param actual the actual value
* @param expected the expected value
*/
public static void assertEquals(Iterator<?> actual, Iterator<?> expected) {
public static void assertEquals(@Nullable Iterator<?> actual, @Nullable Iterator<?> expected) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
public static void assertEquals(@Nullable Iterator<?> actual, @Nullable Iterator<?> expected) {
public static void assertEquals(@Nullable Iterator<@Nullable ?> actual, @Nullable Iterator<@Nullable ?> expected) {

*/
static boolean wasFailureDueToTimeout(ITestResult result) {
Throwable cause = result.getThrowable();
@Nullable Throwable cause = result.getThrowable();
Copy link
Contributor

Choose a reason for hiding this comment

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

Technically speaking, @Nullable should be automatically inferred for local variables, so this could probably be omitted

Suggested change
@Nullable Throwable cause = result.getThrowable();
Throwable cause = result.getThrowable();

Copy link
Member Author

Choose a reason for hiding this comment

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

I suppose you're right.

It means I should not use TypeUseLocation.ALL in @DefaultQualifier(value = NonNull.class, locations = TypeUseLocation.ALL)
Any other option I should exclude? https://checkerframework.org/api/org/checkerframework/framework/qual/TypeUseLocation.html

@@ -52,7 +53,7 @@ public static void addClassLoader(final ClassLoader loader) {

static List<ClassLoader> appendContextualClassLoaders(List<ClassLoader> currentLoaders) {
List<ClassLoader> allClassLoaders = Lists.newArrayList();
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
@Nullable ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
@Nullable ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();

?

} else {
m.addAll(extractedMethod.getValue());
}
@Nullable Class<?> parent = clazz.getSuperclass();
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
@Nullable Class<?> parent = clazz.getSuperclass();
Class<?> parent = clazz.getSuperclass();

private boolean m_enabled = true;

public ConstructorOrMethod(Method m) {
m_method = m;
m_constructor = null;
Copy link
Contributor

Choose a reason for hiding this comment

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

Default value is null anyway, so does it make sense to assign it with null?

@vlsi
Copy link
Contributor

vlsi commented Aug 8, 2023

I would suggest merging errorprone first as it would require much fewer changes.

@juherr
Copy link
Member Author

juherr commented Aug 8, 2023

@vlsi Thanks for the review. I think your suggestion is a good strategy and I will make another PR with errorprone only.

Any idea why I'm not able to use build-parameters? The generated plugin is not found here https://github.com/testng-team/testng/pull/2941/files#diff-5bb00f6e0b0be0ec62ea3824c3888e27921683447cea9fb16bdd9f859f7881acR5

@juherr juherr mentioned this pull request Aug 15, 2023
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.

3 participants