From 830b312d9ec1bbe61a5401ffb500f9420b51be9a Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Fri, 20 Mar 2020 07:17:29 +0000 Subject: [PATCH] JDK 13 Compatibility (#116) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add jdk 13 to build matrix * Adjust indentation * Adjust indentation * Bump kemitix-maven-tiles from 1.2.0 to 2.4.1 * Fix TypeAlias.equals(Object) does not check for null argument net.kemitix.mon.TypeAlias.equals(Object) does not check for null argument [net.kemitix.mon.TypeAlias] At TypeAlias.java:[lines 82-88] NP_EQUALS_SHOULD_HANDLE_NULL_ARGUMENT * Fix TypeAlias.flatMap(Function) declares unbound method template parameter [ERROR] Method net.kemitix.mon.TypeAlias.flatMap(Function) declares unbound method template parameter(s) [net.kemitix.mon.TypeAlias] At TypeAlias.java:[line 72] UMTP_UNBOUND_METHOD_TEMPLATE_PARAMETER * Fix Lazy has a circular dependency with other classes [ERROR] Class net.kemitix.mon.lazy.Lazy has a circular dependency with other classes [net.kemitix.mon.lazy.Lazy] At Lazy.java:[lines 36-46] FCCD_FIND_CLASS_CIRCULAR_DEPENDENCY * Fix Synchronization performed on AtomicReference [ERROR] Synchronization performed on java.util.concurrent.atomic.AtomicReference in net.kemitix.mon.lazy.LazySupplier.value() [net.kemitix.mon.lazy.LazySupplier] At LazySupplier.java:[line 61] JLM_JSR166_UTILCONCURRENT_MONITORENTER * Fix Just.orElseThrow(Supplier) declares throwing an exception that isn't thrown [ERROR] Non derivable method net.kemitix.mon.maybe.Just.orElseThrow(Supplier) declares throwing an exception that isn't thrown [net.kemitix.mon.maybe.Just] At Just.java:[line 102] BED_BOGUS_EXCEPTION_DECLARATION * Fix Maybe has a circular dependency with other classes [ERROR] Class net.kemitix.mon.maybe.Maybe has a circular dependency with other classes [net.kemitix.mon.maybe.Maybe] At Maybe.java:[lines 40-94] FCCD_FIND_CLASS_CIRCULAR_DEPENDENCY * Fix Maybe.findFirst(Stream) uses immediate execution of a block [ERROR] Method net.kemitix.mon.maybe.Maybe.findFirst(Stream) uses immediate execution of a block of code that is often not used [net.kemitix.mon.maybe.Maybe] At Maybe.java:[line 94] OI_OPTIONAL_ISSUES_USES_IMMEDIATE_EXECUTION * Fix Success/Result/Err has a circular dependency [ERROR] Class net.kemitix.mon.result.Err has a circular dependency with other classes [net.kemitix.mon.result.Err] At Err.java: FCCD_FIND_CLASS_CIRCULAR_DEPENDENCY * Fix GeneralisedTree has a circular dependency [ERROR] Class net.kemitix.mon.tree.GeneralisedTree has a circular dependency with other classes [net.kemitix.mon.tree.GeneralisedTree] At GeneralisedTree.java:[lines 39-80] FCCD_FIND_CLASS_CIRCULAR_DEPENDENCY * Supress warning about boxing a boolean NAB_NEEDLESS_BOOLEAN_CONSTANT_CONVERSION Without creating a whole reimplemention of Maybe/Just/Nothing purely for `boolean` primitives, we can’t avoid this boxing. * Supress store before return warnings in Lombok generate hashCode USBR_UNNECESSARY_STORE_BEFORE_RETURN The annotation has to be used at the class level, which unfortunately means we have no store-before-return checks for the rest of the class. * Suppress warning about unused parameter The type parameter for `Tree.builder(type)` is used to specify the parameterised type of the return value. * Checkstyle fixups * [changelog] updated --- .github/workflows/maven-build.yml | 16 ++++---- .github/workflows/sonatype-deploy.yml | 28 +++++++------- CHANGELOG.org | 2 + pom.xml | 9 ++++- src/main/java/net/kemitix/mon/TypeAlias.java | 5 +-- .../net/kemitix/mon/lazy/LazySupplier.java | 5 ++- src/main/java/net/kemitix/mon/maybe/Just.java | 5 ++- .../java/net/kemitix/mon/maybe/Maybe.java | 2 +- .../java/net/kemitix/mon/maybe/Nothing.java | 3 +- src/main/java/net/kemitix/mon/result/Err.java | 10 ++--- .../java/net/kemitix/mon/result/Result.java | 38 +++++++++++++++++++ .../java/net/kemitix/mon/result/Success.java | 10 ++--- .../net/kemitix/mon/tree/GeneralisedTree.java | 4 +- .../net/kemitix/mon/tree/MutableTree.java | 2 + .../kemitix/mon/tree/MutableTreeBuilder.java | 11 +++++- src/main/java/net/kemitix/mon/tree/Tree.java | 3 ++ .../java/net/kemitix/mon/TypeAliasTest.java | 12 ++++++ 17 files changed, 120 insertions(+), 45 deletions(-) diff --git a/.github/workflows/maven-build.yml b/.github/workflows/maven-build.yml index 367d5d2..470baeb 100644 --- a/.github/workflows/maven-build.yml +++ b/.github/workflows/maven-build.yml @@ -14,12 +14,12 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [ 8, 11 ] + java: [ 8, 11, 13 ] steps: - - uses: actions/checkout@v2 - - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@v1 - with: - java-version: ${{ matrix.java }} - - name: Build with Maven - run: mvn -B install + - uses: actions/checkout@v2 + - name: Set up JDK ${{ matrix.java }} + uses: actions/setup-java@v1 + with: + java-version: ${{ matrix.java }} + - name: Build with Maven + run: mvn -B install diff --git a/.github/workflows/sonatype-deploy.yml b/.github/workflows/sonatype-deploy.yml index 0db51e7..192bf3c 100644 --- a/.github/workflows/sonatype-deploy.yml +++ b/.github/workflows/sonatype-deploy.yml @@ -8,17 +8,17 @@ jobs: deploy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - name: Build with Maven - run: mvn -B install - - name: Nexus Repo Publish - run: sh .github/deploy.sh - env: - NEXUS_USERNAME: ${{ secrets.NEXUS_USERNAME }} - NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }} - GPG_KEYNAME: ${{ secrets.GPG_KEYNAME }} - GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + - uses: actions/checkout@v2 + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Build with Maven + run: mvn -B install + - name: Nexus Repo Publish + run: sh .github/deploy.sh + env: + NEXUS_USERNAME: ${{ secrets.NEXUS_USERNAME }} + NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }} + GPG_KEYNAME: ${{ secrets.GPG_KEYNAME }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} diff --git a/CHANGELOG.org b/CHANGELOG.org index 3794191..7e3348b 100644 --- a/CHANGELOG.org +++ b/CHANGELOG.org @@ -10,9 +10,11 @@ The format is based on [[https://keepachangelog.com/en/1.0.0/][Keep a Changelog] ** Added * Add github actions config (#113) + * Add JDK 13 compatibility (#116) ** Dependencies + * Bump kemitix-maven-tiles from 1.2.0 to 2.4.1 (#116) * Bump assertj-core from 3.13.2 to 3.15.0 (#106) * Bump junit-bom from 5.5.2 to 5.6.0 (#105) * Bump tiles-maven-plugin from 2.15 to 2.16 (#101) diff --git a/pom.xml b/pom.xml index 7af215d..132493f 100644 --- a/pom.xml +++ b/pom.xml @@ -38,11 +38,12 @@ 3.15.0 1.18.12 2.16 - 1.2.0 + 2.4.1 net.kemitix.mon 5.0.0 1.5.0 0.12 + 4.0.1 @@ -75,6 +76,12 @@ ${assertj.version} test + + com.github.spotbugs + spotbugs-annotations + ${spotbugs.version} + provided + diff --git a/src/main/java/net/kemitix/mon/TypeAlias.java b/src/main/java/net/kemitix/mon/TypeAlias.java index eb8ea26..4422b4d 100644 --- a/src/main/java/net/kemitix/mon/TypeAlias.java +++ b/src/main/java/net/kemitix/mon/TypeAlias.java @@ -64,11 +64,10 @@ public abstract class TypeAlias { * Map the TypeAlias into another TypeAlias. * * @param f the function to create the new value - * @param the type of the new value within a TypeAlias * @param the type of the TypeAlias superclass containing the new value * @return a TypeAlias */ - public final > U flatMap(final Function f) { + public final > U flatMap(final Function f) { return f.apply(value); } @@ -85,7 +84,7 @@ public abstract class TypeAlias { return otherValueClass.equals(getValue().getClass()) && other.value.equals(getValue()); } - return map(o::equals); + return o != null && map(o::equals); } @Override diff --git a/src/main/java/net/kemitix/mon/lazy/LazySupplier.java b/src/main/java/net/kemitix/mon/lazy/LazySupplier.java index 061c61b..7460dcd 100644 --- a/src/main/java/net/kemitix/mon/lazy/LazySupplier.java +++ b/src/main/java/net/kemitix/mon/lazy/LazySupplier.java @@ -38,6 +38,7 @@ class LazySupplier implements Lazy { private final Supplier supplier; private final AtomicBoolean evaluated = new AtomicBoolean(false); private final AtomicReference value = new AtomicReference<>(); + private final Object lock = new Object(); /** * Creates a new Lazy wrapper for the Supplier. @@ -58,7 +59,7 @@ class LazySupplier implements Lazy { if (evaluated.get()) { return value.get(); } - synchronized (value) { + synchronized (lock) { if (!evaluated.get()) { value.set(supplier.get()); evaluated.set(true); @@ -69,7 +70,7 @@ class LazySupplier implements Lazy { @Override public Lazy map(final Function f) { - return Lazy.of(() -> f.apply(value())); + return new LazySupplier(() -> f.apply(value())); } } diff --git a/src/main/java/net/kemitix/mon/maybe/Just.java b/src/main/java/net/kemitix/mon/maybe/Just.java index 9a7c96b..b16cbd8 100644 --- a/src/main/java/net/kemitix/mon/maybe/Just.java +++ b/src/main/java/net/kemitix/mon/maybe/Just.java @@ -85,11 +85,12 @@ final class Just implements Maybe { } @Override + @SuppressWarnings("unchecked") public Maybe filter(final Predicate predicate) { if (predicate.test(value)) { return this; } - return Maybe.nothing(); + return (Maybe) Nothing.INSTANCE; } @Override @@ -98,7 +99,7 @@ final class Just implements Maybe { } @Override - public T orElseThrow(final Supplier e) throws X { + public T orElseThrow(final Supplier e) { return value; } diff --git a/src/main/java/net/kemitix/mon/maybe/Maybe.java b/src/main/java/net/kemitix/mon/maybe/Maybe.java index 3041bdc..1808e99 100644 --- a/src/main/java/net/kemitix/mon/maybe/Maybe.java +++ b/src/main/java/net/kemitix/mon/maybe/Maybe.java @@ -91,7 +91,7 @@ public interface Maybe extends Functor> { public static Maybe findFirst(Stream stream) { return stream.findFirst() .map(Maybe::just) - .orElse(Maybe.nothing()); + .orElseGet(Maybe::nothing); } /** diff --git a/src/main/java/net/kemitix/mon/maybe/Nothing.java b/src/main/java/net/kemitix/mon/maybe/Nothing.java index 2d4791c..47f651c 100644 --- a/src/main/java/net/kemitix/mon/maybe/Nothing.java +++ b/src/main/java/net/kemitix/mon/maybe/Nothing.java @@ -50,8 +50,9 @@ final class Nothing implements Maybe { } @Override + @SuppressWarnings("unchecked") public Maybe flatMap(final Function> f) { - return Maybe.nothing(); + return (Maybe) INSTANCE; } @Override diff --git a/src/main/java/net/kemitix/mon/result/Err.java b/src/main/java/net/kemitix/mon/result/Err.java index e2c0a67..a6d0f04 100644 --- a/src/main/java/net/kemitix/mon/result/Err.java +++ b/src/main/java/net/kemitix/mon/result/Err.java @@ -54,12 +54,12 @@ class Err implements Result { @Override public Result flatMap(final Function> f) { - return Result.error(error); + return err(error); } @Override public Result map(final Function f) { - return Result.error(error); + return err(error); } @Override @@ -69,7 +69,7 @@ class Err implements Result { @Override public Result> maybe(final Predicate predicate) { - return Result.error(error); + return err(error); } @Override @@ -108,7 +108,7 @@ class Err implements Result { @Override public Result andThen(final Function> f) { - return Result.error(error); + return err(error); } @Override @@ -118,7 +118,7 @@ class Err implements Result { @Override public Result reduce(final Result identify, final BinaryOperator operator) { - return Result.error(error); + return this; } @Override diff --git a/src/main/java/net/kemitix/mon/result/Result.java b/src/main/java/net/kemitix/mon/result/Result.java index 76d852b..d0942c0 100644 --- a/src/main/java/net/kemitix/mon/result/Result.java +++ b/src/main/java/net/kemitix/mon/result/Result.java @@ -49,6 +49,17 @@ public interface Result extends Functor> { .orElseGet(() -> Result.error(error.get())); } + /** + * Create a Result for an error. + * + * @param error the error (Throwable) + * @param the type had the result been a success + * @return an error Result + */ + public default Result err(final Throwable error) { + return new Err<>(error); + } + /** * Create a Result for an error. * @@ -60,6 +71,22 @@ public interface Result extends Functor> { return new Err<>(error); } + /** + * Create a Result for a output of the Callable. + * + * @param callable the callable to produce the result + * @param the type of the value + * @return a Result + */ + @SuppressWarnings("illegalcatch") + public default Result result(final Callable callable) { + try { + return Result.ok(callable.call()); + } catch (final Exception e) { + return Result.error(e); + } + } + /** * Create a Result for a output of the Callable. * @@ -76,6 +103,17 @@ public interface Result extends Functor> { } } + /** + * Create a Result for a success. + * + * @param value the value + * @param the type of the value + * @return a successful Result + */ + public default Result success(final T value) { + return new Success<>(value); + } + /** * Create a Result for a success. * diff --git a/src/main/java/net/kemitix/mon/result/Success.java b/src/main/java/net/kemitix/mon/result/Success.java index ce49401..ee8a49e 100644 --- a/src/main/java/net/kemitix/mon/result/Success.java +++ b/src/main/java/net/kemitix/mon/result/Success.java @@ -54,7 +54,7 @@ class Success implements Result { @Override public Result map(final Function f) { - return Result.ok(f.apply(value)); + return success(f.apply(value)); } @Override @@ -65,9 +65,9 @@ class Success implements Result { @Override public Result> maybe(final Predicate predicate) { if (predicate.test(value)) { - return Result.ok(Maybe.just(value)); + return success(Maybe.just(value)); } - return Result.ok(Maybe.nothing()); + return success(Maybe.nothing()); } @Override @@ -103,7 +103,7 @@ class Success implements Result { @Override public Result andThen(final Function> f) { - return Result.of(f.apply(value)); + return result(f.apply(value)); } @Override @@ -113,7 +113,7 @@ class Success implements Result { @Override public Result reduce(final Result identity, final BinaryOperator operator) { - return flatMap(a -> identity.flatMap(b -> Result.of(() -> operator.apply(a, b)))); + return flatMap(a -> identity.flatMap(b -> result(() -> operator.apply(a, b)))); } @Override diff --git a/src/main/java/net/kemitix/mon/tree/GeneralisedTree.java b/src/main/java/net/kemitix/mon/tree/GeneralisedTree.java index d0cb9cb..e833b49 100644 --- a/src/main/java/net/kemitix/mon/tree/GeneralisedTree.java +++ b/src/main/java/net/kemitix/mon/tree/GeneralisedTree.java @@ -21,6 +21,7 @@ package net.kemitix.mon.tree; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import lombok.EqualsAndHashCode; import net.kemitix.mon.maybe.Maybe; @@ -36,6 +37,7 @@ import java.util.function.Function; * * @author Paul Campbell (pcampbell@kemitix.net) */ +@SuppressFBWarnings("USBR_UNNECESSARY_STORE_BEFORE_RETURN") @EqualsAndHashCode class GeneralisedTree implements Tree, TreeMapper { @@ -62,7 +64,7 @@ class GeneralisedTree implements Tree, TreeMapper { */ @Override public Tree map(final Function f) { - return Tree.of(f.apply(item), mapTrees(f, subTrees())); + return new GeneralisedTree<>(f.apply(item), mapTrees(f, subTrees())); } @Override diff --git a/src/main/java/net/kemitix/mon/tree/MutableTree.java b/src/main/java/net/kemitix/mon/tree/MutableTree.java index e4be977..9948ba8 100644 --- a/src/main/java/net/kemitix/mon/tree/MutableTree.java +++ b/src/main/java/net/kemitix/mon/tree/MutableTree.java @@ -21,6 +21,7 @@ package net.kemitix.mon.tree; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import lombok.EqualsAndHashCode; import net.kemitix.mon.maybe.Maybe; @@ -37,6 +38,7 @@ import java.util.stream.Collectors; * * @author Paul Campbell (pcampbell@kemitix.net) */ +@SuppressFBWarnings("USBR_UNNECESSARY_STORE_BEFORE_RETURN") @EqualsAndHashCode @SuppressWarnings("methodcount") class MutableTree implements Tree, TreeMapper { diff --git a/src/main/java/net/kemitix/mon/tree/MutableTreeBuilder.java b/src/main/java/net/kemitix/mon/tree/MutableTreeBuilder.java index da07431..0ce7ef4 100644 --- a/src/main/java/net/kemitix/mon/tree/MutableTreeBuilder.java +++ b/src/main/java/net/kemitix/mon/tree/MutableTreeBuilder.java @@ -21,6 +21,7 @@ package net.kemitix.mon.tree; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import net.kemitix.mon.maybe.Maybe; import java.util.function.Function; @@ -84,8 +85,14 @@ class MutableTreeBuilder implements TreeBuilder { .map(Tree::builder)); } - private Boolean matchesItem(final T childItem, final MutableTree tree) { - return tree.item().map(childItem::equals).orElse(false); + @SuppressFBWarnings("NAB_NEEDLESS_BOOLEAN_CONSTANT_CONVERSION") + private boolean matchesItem( + final T childItem, + final MutableTree tree + ) { + return tree.item() + .map(childItem::equals) + .orElse(false); } } diff --git a/src/main/java/net/kemitix/mon/tree/Tree.java b/src/main/java/net/kemitix/mon/tree/Tree.java index e7933c9..66ce89c 100644 --- a/src/main/java/net/kemitix/mon/tree/Tree.java +++ b/src/main/java/net/kemitix/mon/tree/Tree.java @@ -21,6 +21,7 @@ package net.kemitix.mon.tree; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import net.kemitix.mon.Functor; import net.kemitix.mon.maybe.Maybe; @@ -70,6 +71,8 @@ public interface Tree extends Functor> { * * @return a TreeBuilder */ + @SuppressFBWarnings(value = "UP_UNUSED_PARAMETER", + justification = "Use the type parameter to fingerprint the return type") public static TreeBuilder builder(final Class type) { return new MutableTreeBuilder<>(); } diff --git a/src/test/java/net/kemitix/mon/TypeAliasTest.java b/src/test/java/net/kemitix/mon/TypeAliasTest.java index 7c89ad3..2073386 100644 --- a/src/test/java/net/kemitix/mon/TypeAliasTest.java +++ b/src/test/java/net/kemitix/mon/TypeAliasTest.java @@ -1,6 +1,7 @@ package net.kemitix.mon; import org.assertj.core.util.Strings; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import java.util.Arrays; @@ -116,6 +117,17 @@ class TypeAliasTest { assertThat(value).isEqualTo("'text'"); } + @Test + @DisplayName("equals other is null then not equals") + void whenOtherNullEqualsIsFalse() { + //given + final AnAlias anAlias = AnAlias.of("text"); + //then + boolean result = anAlias.equals(null); + //then + assertThat(result).isFalse(); + } + private static class AnAlias extends TypeAlias { /**