From a5fe4d792822b373008f82e65c5d1974acc3320a Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 2 Jan 2026 17:12:20 -0700 Subject: [PATCH] Add annotations --- .../commands/locate/LocateCommandAddon.java | 2 +- .../api/util/function/FunctionUtils.java | 39 +++++++++------ .../terra/api/util/generic/control/Monad.java | 20 +++++--- .../api/util/generic/data/BiFunctor.java | 22 +++++++-- .../terra/api/util/generic/data/Functor.java | 6 ++- .../api/util/generic/data/LinkedList.java | 48 ++++++++++++++----- .../terra/api/util/generic/data/Monoid.java | 11 +++-- .../api/util/generic/data/types/Either.java | 40 +++++++++++----- .../api/util/generic/data/types/Maybe.java | 16 ++++--- .../api/util/generic/data/types/Pair.java | 4 +- 10 files changed, 142 insertions(+), 66 deletions(-) diff --git a/common/addons/command-locate/src/main/java/com/dfsek/terra/addons/commands/locate/LocateCommandAddon.java b/common/addons/command-locate/src/main/java/com/dfsek/terra/addons/commands/locate/LocateCommandAddon.java index b60caef03..baec07c4a 100644 --- a/common/addons/command-locate/src/main/java/com/dfsek/terra/addons/commands/locate/LocateCommandAddon.java +++ b/common/addons/command-locate/src/main/java/com/dfsek/terra/addons/commands/locate/LocateCommandAddon.java @@ -27,7 +27,7 @@ import com.dfsek.terra.api.util.reflection.TypeKey; import com.dfsek.terra.api.world.World; import com.dfsek.terra.api.world.biome.Biome; -import static com.dfsek.terra.api.util.function.FunctionUtils.collapse; +import static com.dfsek.terra.api.util.generic.data.types.Either.collapse; public class LocateCommandAddon implements AddonInitializer { diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/function/FunctionUtils.java b/common/api/src/main/java/com/dfsek/terra/api/util/function/FunctionUtils.java index 1961c754d..8eefdd730 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/function/FunctionUtils.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/function/FunctionUtils.java @@ -2,40 +2,39 @@ package com.dfsek.terra.api.util.function; import com.dfsek.terra.api.util.generic.data.types.Either; -import java.util.Optional; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; import java.util.function.Consumer; import java.util.function.Function; public final class FunctionUtils { - private FunctionUtils() {} + private FunctionUtils() { } - public static Function lift(Consumer c) { + @Contract("_ -> new") + public static @NotNull Function lift(@NotNull Consumer c) { + Objects.requireNonNull(c); return co -> { c.accept(co); return co; }; } - @SuppressWarnings("unchecked") - public static Either toEither(Optional o, L de) { - return (Either) o.map(Either::right).orElseGet(() -> Either.left(de)); - } - - public static T collapse(Either either) { - return either.collect(Function.identity(), Function.identity()); - } - - public static U throw_(T e) throws T { + @Contract("_ -> fail") + public static @NotNull U throw_(@NotNull T e) throws T { throw e; } @SuppressWarnings("unchecked") - public static U sneakyThrow(Throwable e) throws E { + @Contract("_ -> fail") + public static @NotNull U sneakyThrow(@NotNull Throwable e) throws E { throw (E) e; } - public static Function> liftTry(Function f) { + @Contract(pure = true, value = "_ -> new") + public static @NotNull Function> liftTry(@NotNull Function f) { return s -> { try { return Either.right(f.apply(s)); @@ -45,4 +44,14 @@ public final class FunctionUtils { }; } + @Contract(pure = true, value = "_ -> new") + public static @NotNull Function> liftTryUnsafe(@NotNull Function f) { + return s -> { + try { + return Either.right(f.apply(s)); + } catch(Throwable e) { + return Either.left(e); + } + }; + } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/control/Monad.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/control/Monad.java index 29ae017c0..bf3f73a7a 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/generic/control/Monad.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/control/Monad.java @@ -3,6 +3,10 @@ package com.dfsek.terra.api.util.generic.control; import com.dfsek.terra.api.util.generic.data.Functor; import com.dfsek.terra.api.util.generic.kinds.K; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; import java.util.function.Function; @@ -10,17 +14,21 @@ import java.util.function.Function; * A monad is a monoid in the category of endofunctors. */ public interface Monad> extends Functor, K { - Monad bind(Function> map); + @Contract(pure = true, value = "_ -> new") + @NotNull Monad bind(@NotNull Function> map); - Monad pure(T1 t); + @Contract(pure = true, value = "_ -> new") + @NotNull Monad pure(@NotNull T1 t); @Override - default Monad map(Function map) { - return bind(map.andThen(this::pure)); + @Contract(pure = true, value = "_ -> new") + default @NotNull Monad map(@NotNull Function map) { + return bind(Objects.requireNonNull(map).andThen(this::pure)); } // almost all well-known applicative functors are also monads, so we can just put that here. - default Monad apply(Monad, M> amap) { - return amap.bind(this::map); + @Contract(pure = true, value = "_ -> new") + default @NotNull Monad apply(@NotNull Monad, M> amap) { + return Objects.requireNonNull(amap).bind(this::map); } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/BiFunctor.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/BiFunctor.java index b869eecb9..db93c4add 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/BiFunctor.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/BiFunctor.java @@ -2,29 +2,41 @@ package com.dfsek.terra.api.util.generic.data; import com.dfsek.terra.api.util.generic.data.types.Pair; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; import java.util.function.Consumer; import java.util.function.Function; public interface BiFunctor> { - static > Consumer> consumeLeft(Consumer consumer) { + @Contract("_ -> new") + static > @NotNull Consumer> consumeLeft(@NotNull Consumer consumer) { + Objects.requireNonNull(consumer); return pair -> pair.mapLeft(p -> { consumer.accept(p); return p; }); } - static Consumer> consumeRight(Consumer consumer) { + @Contract("_ -> new") + static > @NotNull Consumer> consumeRight(@NotNull Consumer consumer) { + Objects.requireNonNull(consumer); return pair -> pair.mapRight(p -> { consumer.accept(p); return p; }); } - BiFunctor mapLeft(Function map); - BiFunctor mapRight(Function map); + @Contract(pure = true, value = "_ -> new") + @NotNull BiFunctor mapLeft(@NotNull Function map); - default BiFunctor bimap(Function left, Function right) { + @Contract(pure = true, value = "_ -> new") + @NotNull BiFunctor mapRight(@NotNull Function map); + + @Contract(pure = true, value = "_, _-> new") + default @NotNull BiFunctor bimap(@NotNull Function left, @NotNull Function right) { return mapLeft(left).mapRight(right); } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/Functor.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/Functor.java index 452f1ea85..69023acb0 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/Functor.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/Functor.java @@ -2,9 +2,13 @@ package com.dfsek.terra.api.util.generic.data; import com.dfsek.terra.api.util.generic.kinds.K; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + import java.util.function.Function; public interface Functor> extends K { - Functor map(Function map); + @Contract(pure = true, value = "_ -> new") + @NotNull Functor map(@NotNull Function map); } diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/LinkedList.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/LinkedList.java index 16b9f50c1..ba57ceade 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/LinkedList.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/LinkedList.java @@ -3,59 +3,81 @@ package com.dfsek.terra.api.util.generic.data; import com.dfsek.terra.api.util.generic.control.Monad; import com.dfsek.terra.api.util.generic.data.types.Maybe; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.dataflow.qual.Pure; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.function.Function; public sealed interface LinkedList extends Monad>, Monoid> { @Override - LinkedList bind(Function>> map); + @Contract(pure = true, value = "_ -> new") + @NotNull LinkedList bind(@NotNull Function>> map); @Override - default LinkedList pure(T1 t) { + @Contract(pure = true, value = "_ -> new") + default @NotNull LinkedList pure(@NotNull T1 t) { return of(t); } @Override - LinkedList map(Function map); + @Contract(pure = true, value = "_ -> new") + @NotNull LinkedList map(@NotNull Function map); @Override - default LinkedList identity() { + @Contract(pure = true, value = "-> new") + default @NotNull LinkedList identity() { return empty(); } + @Contract(pure = true, value = "-> new") default Maybe head() { return get(0); } LinkedList tail(); + @Contract(pure = true) int length(); + @Contract(pure = true) Maybe get(int index); + @Contract(pure = true, value = "_ -> new") LinkedList add(T value); - default LinkedList prepend(T value) { - return new Cons<>(value, this); + @NotNull + @Contract(pure = true, value = "_ -> new") + default LinkedList prepend(@NotNull T value) { + return new Cons<>(Objects.requireNonNull(value), this); } + @Contract(mutates = "param") > C toCollection(C collection); + @NotNull + @Contract(pure = true, value = "-> new") default List toList() { return toCollection(new ArrayList<>()); } + @NotNull + @Contract(pure = true, value = "-> new") default Set toSet() { return toCollection(new HashSet<>()); } @Override - LinkedList multiply(Monoid> t); + @NotNull + LinkedList multiply(@NotNull Monoid> t); static LinkedList of(T value) { return new Cons<>(value, empty()); @@ -68,12 +90,12 @@ public sealed interface LinkedList extends Monad>, Monoid(T value, LinkedList tail) implements LinkedList { @Override - public LinkedList bind(Function>> map) { + public @NotNull LinkedList bind(@NotNull Function>> map) { return ((LinkedList) map.apply(value)).multiply(tail.bind(map)); } @Override - public LinkedList map(Function map) { + public @NotNull LinkedList map(@NotNull Function map) { return new Cons<>(map.apply(value), tail.map(map)); } @@ -101,7 +123,7 @@ public sealed interface LinkedList extends Monad>, Monoid multiply(Monoid> t) { + public @NotNull LinkedList multiply(@NotNull Monoid> t) { return new Cons<>(value, tail.multiply(t)); } } @@ -111,13 +133,13 @@ public sealed interface LinkedList extends Monad>, Monoid LinkedList bind(Function>> map) { + public @NotNull LinkedList bind(@NotNull Function>> map) { return (LinkedList) this; } @Override @SuppressWarnings("unchecked") - public LinkedList map(Function map) { + public @NotNull LinkedList map(@NotNull Function map) { return (LinkedList) this; } @@ -147,7 +169,7 @@ public sealed interface LinkedList extends Monad>, Monoid multiply(Monoid> t) { + public @NotNull LinkedList multiply(@NotNull Monoid> t) { return (LinkedList) t; } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/Monoid.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/Monoid.java index ed5fb2334..db13e80a9 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/Monoid.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/Monoid.java @@ -2,9 +2,14 @@ package com.dfsek.terra.api.util.generic.data; import com.dfsek.terra.api.util.generic.kinds.K; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; -public interface Monoid> extends K{ - Monoid identity(); - Monoid multiply(Monoid t); +public interface Monoid> extends K { + @Contract(pure = true, value = "-> new") + @NotNull Monoid identity(); + + @Contract(pure = true, value = "_ -> new") + @NotNull Monoid multiply(@NotNull Monoid t); } diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Either.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Either.java index 37d1e11cc..7a60c1713 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Either.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Either.java @@ -17,38 +17,52 @@ import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import java.util.Objects; +import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; public sealed interface Either extends Monad>, BiFunctor> { - default Either ifLeft(Consumer action) { + static T collapse(Either either) { + return either.collect(Function.identity(), Function.identity()); + } + + @SuppressWarnings("unchecked") + static Either toEither(Optional o, L de) { + return (Either) o.map(Either::right).orElseGet(() -> left(de)); + } + + @NotNull + @Contract("_ -> this") + default Either ifLeft(@NotNull Consumer action) { return mapLeft(FunctionUtils.lift(action)); } - default Either ifRight(Consumer action) { + @NotNull + @Contract("_ -> this") + default Either ifRight(@NotNull Consumer action) { return mapRight(FunctionUtils.lift(action)); } // Either is a functor in its right parameter. @Override - default Either map(Function map) { + default @NotNull Either map(@NotNull Function map) { return mapRight(map); } @Override - default Either pure(T1 t) { + default @NotNull Either pure(@NotNull T1 t) { return right(t); } @Override - Either bind(Function>> map); + @NotNull Either bind(@NotNull Function>> map); @Override - Either mapLeft(Function f); + @NotNull Either mapLeft(@NotNull Function f); @Override - Either mapRight(Function f); + @NotNull Either mapRight(@NotNull Function f); Maybe getLeft(); @@ -93,18 +107,18 @@ public sealed interface Either extends Monad>, BiFunctor Either bind(Function>> map) { + public @NotNull Either bind(@NotNull Function>> map) { return (Either) this; } @Override - public Either mapLeft(Function f) { + public @NotNull Either mapLeft(@NotNull Function f) { return new Left<>(f.apply(value)); } @SuppressWarnings({ "unchecked" }) @Override - public Either mapRight(Function f) { + public @NotNull Either mapRight(@NotNull Function f) { return (Either) this; } @@ -142,18 +156,18 @@ public sealed interface Either extends Monad>, BiFunctor(R value) implements Either { @Override - public Either bind(Function>> map) { + public @NotNull Either bind(@NotNull Function>> map) { return (Either) map.apply(value); } @SuppressWarnings({ "unchecked" }) @Override - public Either mapLeft(Function f) { + public @NotNull Either mapLeft(@NotNull Function f) { return (Either) this; } @Override - public Either mapRight(Function f) { + public @NotNull Either mapRight(@NotNull Function f) { return new Right<>(f.apply(value)); } diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Maybe.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Maybe.java index 7aa1b683e..9ee201c7c 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Maybe.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Maybe.java @@ -3,6 +3,8 @@ package com.dfsek.terra.api.util.generic.data.types; import com.dfsek.terra.api.util.generic.control.Monad; import com.dfsek.terra.api.util.generic.data.LinkedList; +import org.jetbrains.annotations.NotNull; + import java.util.NoSuchElementException; import java.util.Optional; import java.util.function.Consumer; @@ -14,12 +16,12 @@ import java.util.stream.Stream; public sealed interface Maybe extends Monad> { @Override - default Maybe pure(T1 t) { + default @NotNull Maybe pure(@NotNull T1 t) { return just(t); } @Override - Maybe bind(Function>> map); + @NotNull Maybe bind(@NotNull Function>> map); Optional toOptional(); @@ -30,7 +32,7 @@ public sealed interface Maybe extends Monad> { boolean isJust(); @Override - Maybe map(Function map); + @NotNull Maybe map(@NotNull Function map); default T get(T def) { return get(() -> def); @@ -137,7 +139,7 @@ public sealed interface Maybe extends Monad> { } @Override - public Maybe map(Function map) { + public @NotNull Maybe map(@NotNull Function map) { return just(map.apply(value)); } @@ -147,7 +149,7 @@ public sealed interface Maybe extends Monad> { } @Override - public Maybe bind(Function>> map) { + public @NotNull Maybe bind(@NotNull Function>> map) { return (Maybe) map.apply(value); } } @@ -155,7 +157,7 @@ public sealed interface Maybe extends Monad> { record Nothing() implements Maybe { @Override - public Maybe bind(Function>> map) { + public @NotNull Maybe bind(@NotNull Function>> map) { return nothing(); } @@ -181,7 +183,7 @@ public sealed interface Maybe extends Monad> { @Override @SuppressWarnings("unchecked") - public Maybe map(Function map) { + public @NotNull Maybe map(@NotNull Function map) { return (Maybe) this; } diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Pair.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Pair.java index 484897670..06c3ae02d 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Pair.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Pair.java @@ -21,11 +21,11 @@ import java.util.function.Predicate; public record Pair(L left, R right) implements BiFunctor> { private static final Pair NULL = new Pair<>(null, null); - public Pair mapLeft(Function function) { + public @NotNull Pair mapLeft(@NotNull Function function) { return of(function.apply(left), right); } - public Pair mapRight(Function function) { + public @NotNull Pair mapRight(@NotNull Function function) { return of(left, function.apply(right)); }