Skip to content

Commit

Permalink
#308: adds support for JSR305's ParametersAreNonnullByDefault annotation
Browse files Browse the repository at this point in the history
  • Loading branch information
jqno committed Jun 11, 2020
1 parent bd5e969 commit 503babb
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 4 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- Initial support for Java 14's records and their [new equality invariant](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Record.html).
- Support for JSR305's `ParametersAreNonnullByDefault` annotation. ([Issue 308](https://github.com/jqno/equalsverifier/issues/308))
### Changed
- Renames the project's main branch to `main`.
- Replaces all references to the word 'black' to 'blue', including those in internal (but accessible) API's.
### Fixed

## [3.3] - 2020-05-14
### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,15 @@ public boolean validate(
AnnotationProperties properties,
AnnotationCache annotationCache,
Set<String> ignoredAnnotations) {
return properties.getArrayValues("value").contains("FIELD");
Set<String> value = properties.getArrayValues("value");
return value.contains("FIELD") || value.contains("PARAMETER");
}
},

/**
* If a class or package is marked with @DefaultAnnotation(Nonnull.class), EqualsVerifier will
* not complain about potential {@link NullPointerException}s being thrown if any of the fields
* in that class or package are null.
* If a class or package is marked with @NonNullByDefault, EqualsVerifier will not complain
* about potential {@link NullPointerException}s being thrown if any of the fields in that class
* or package are null.
*/
ECLIPSE_DEFAULT_ANNOTATION_NONNULL(false, "org.eclipse.jdt.annotation.NonNullByDefault") {
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
package nl.jqno.equalsverifier.integration.extra_features;

import java.util.Objects;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import nl.jqno.equalsverifier.EqualsVerifier;
import nl.jqno.equalsverifier.Warning;
import nl.jqno.equalsverifier.integration.extra_features.nonnull.jsr305.parametersarenonnullbydefault.ParametersAreNonnullByDefaultOnPackage;
import nl.jqno.equalsverifier.testhelpers.ExpectedExceptionTestBase;
import org.junit.Test;

public class AnnotationParametersAreNonnullByDefaultTest extends ExpectedExceptionTestBase {

@Test
public void succeed_whenEqualsDoesntCheckForNull_givenEclipseDefaultAnnotationOnClass() {
EqualsVerifier.forClass(ParametersAreNonnullByDefaultOnClass.class).verify();
}

@Test
public void succeed_whenEqualsDoesntCheckForNull_givenEclipseDefaultAnnotationOnPackage() {
EqualsVerifier.forClass(ParametersAreNonnullByDefaultOnPackage.class).verify();
}

@Test
public void succeed_whenEqualsDoesntCheckForNull_givenEclipseDefaultAnnotationOnOuterClass() {
EqualsVerifier.forClass(ParametersAreNonnullByDefaultOuter.FInner.class).verify();
}

@Test
public void
succeed_whenEqualsDoesntCheckForNull_givenEclipseDefaultAnnotationOnNestedOuterClass() {
EqualsVerifier.forClass(ParametersAreNonnullByDefaultOuter.FMiddle.FInnerInner.class)
.verify();
}

@Test
public void
fail_whenEqualsDoesntCheckForNull_givenEclipseDefaultAndNullableAnnotationOnClass() {
expectFailure("Non-nullity", "equals throws NullPointerException", "on field o");
EqualsVerifier.forClass(ParametersAreNonnullByDefaultWithNullableOnClass.class).verify();
}

@Test
public void
succeed_whenEqualsDoesntCheckForNull_givenEclipseDefaultAndNullableAnnotationOnClassAndWarningSuppressed() {
EqualsVerifier.forClass(ParametersAreNonnullByDefaultWithNullableOnClass.class)
.suppress(Warning.NULL_FIELDS)
.verify();
}

@Test
public void succeed_whenEqualsChecksForNull_givenEclipseDefaultAndNullableAnnotationOnClass() {
EqualsVerifier.forClass(
ParametersAreNonnullByDefaultWithNullableOnClassAndNullCheckInEquals.class)
.verify();
}

@ParametersAreNonnullByDefault
static final class ParametersAreNonnullByDefaultOnClass {
private final Object o;

public ParametersAreNonnullByDefaultOnClass(Object o) {
this.o = o;
}

@Override
public boolean equals(Object obj) {
if (!(obj instanceof ParametersAreNonnullByDefaultOnClass)) {
return false;
}
ParametersAreNonnullByDefaultOnClass other = (ParametersAreNonnullByDefaultOnClass) obj;
return o.equals(other.o);
}

@Override
public int hashCode() {
return Objects.hash(o);
}
}

@ParametersAreNonnullByDefault
static final class ParametersAreNonnullByDefaultOuter {
static final class FInner {
private final Object o;

public FInner(Object o) {
this.o = o;
}

@Override
public boolean equals(Object obj) {
if (!(obj instanceof FInner)) {
return false;
}
FInner other = (FInner) obj;
return o.equals(other.o);
}

@Override
public int hashCode() {
return Objects.hash(o);
}
}

static final class FMiddle {
static final class FInnerInner {
private final Object o;

public FInnerInner(Object o) {
this.o = o;
}

@Override
public boolean equals(Object obj) {
if (!(obj instanceof FInnerInner)) {
return false;
}
FInnerInner other = (FInnerInner) obj;
return o.equals(other.o);
}

@Override
public int hashCode() {
return Objects.hash(o);
}
}
}
}

@ParametersAreNonnullByDefault
static final class ParametersAreNonnullByDefaultWithNullableOnClass {
private final @Nullable Object o;

public ParametersAreNonnullByDefaultWithNullableOnClass(Object o) {
this.o = o;
}

@Override
public final boolean equals(Object obj) {
if (!(obj instanceof ParametersAreNonnullByDefaultWithNullableOnClass)) {
return false;
}
ParametersAreNonnullByDefaultWithNullableOnClass other =
(ParametersAreNonnullByDefaultWithNullableOnClass) obj;
return o.equals(other.o);
}

@Override
public final int hashCode() {
return Objects.hash(o);
}
}

@ParametersAreNonnullByDefault
static final class ParametersAreNonnullByDefaultWithNullableOnClassAndNullCheckInEquals {
private final @Nullable Object o;

public ParametersAreNonnullByDefaultWithNullableOnClassAndNullCheckInEquals(Object o) {
this.o = o;
}

@Override
public final boolean equals(Object obj) {
if (!(obj
instanceof
ParametersAreNonnullByDefaultWithNullableOnClassAndNullCheckInEquals)) {
return false;
}
ParametersAreNonnullByDefaultWithNullableOnClassAndNullCheckInEquals other =
(ParametersAreNonnullByDefaultWithNullableOnClassAndNullCheckInEquals) obj;
return o == null ? other.o == null : o.equals(other.o);
}

@Override
public final int hashCode() {
return Objects.hash(o);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package nl.jqno.equalsverifier.integration.extra_features.nonnull.jsr305.parametersarenonnullbydefault;

import java.util.Objects;

public final class ParametersAreNonnullByDefaultOnPackage {
private final Object o;

public ParametersAreNonnullByDefaultOnPackage(Object o) {
this.o = o;
}

@Override
public boolean equals(Object obj) {
if (!(obj instanceof ParametersAreNonnullByDefaultOnPackage)) {
return false;
}
ParametersAreNonnullByDefaultOnPackage other = (ParametersAreNonnullByDefaultOnPackage) obj;
return o.equals(other.o);
}

@Override
public int hashCode() {
return Objects.hash(o);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/** Applies JSR305's ParametersAreNonnullByDefault annotation to the whole package. */
@ParametersAreNonnullByDefault
package nl.jqno.equalsverifier.integration.extra_features.nonnull.jsr305.parametersarenonnullbydefault;

import javax.annotation.ParametersAreNonnullByDefault;

0 comments on commit 503babb

Please sign in to comment.