1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-06-25 22:53:22 +00:00

Switch the core-api to be non-null by default

We'll do this everywhere eventually, but much easier to do it
incrementally:

 - Use checker framework to default all field/methods/parameters to
   @Nonnull.

 - Start using ErrorProne[1] and NullAway[2] to check for possible null
   pointer issues. I did look into using CheckerFramework, but it's much
   stricter (i.e. it's actually Correct). This is technically good, but
   is a much steeper migration path, which I'm not sure we're prepared
   for yet!

[1]: https://github.com/google/error-prone
[2]: https://github.com/uber/NullAway
This commit is contained in:
Jonathan Coates 2022-11-06 10:28:49 +00:00
parent acc254a1ef
commit c8c128d335
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
30 changed files with 193 additions and 128 deletions

View File

@ -1,6 +1,8 @@
import cc.tweaked.gradle.*
import net.darkhax.curseforgegradle.TaskPublishCurseForge
import net.minecraftforge.gradle.common.util.RunConfig
import org.jetbrains.gradle.ext.compiler
import org.jetbrains.gradle.ext.settings
plugins {
// Build
@ -14,6 +16,7 @@ plugins {
alias(libs.plugins.minotaur)
// Utility
alias(libs.plugins.taskTree)
alias(libs.plugins.ideaExt)
id("cc-tweaked.illuaminate")
id("cc-tweaked.node")
@ -419,3 +422,20 @@ publishing {
}
}
}
idea.project.settings.compiler.javac {
// We want ErrorProne to be present when compiling via IntelliJ, as it offers some helpful warnings
// and errors. Loop through our source sets and find the appropriate flags.
moduleJavacAdditionalOptions = subprojects
.asSequence()
.map { evaluationDependsOn(it.path) }
.flatMap { project ->
val sourceSets = project.extensions.findByType(SourceSetContainer::class) ?: return@flatMap sequenceOf()
sourceSets.asSequence().map { sourceSet ->
val name = "${idea.project.name}.${project.name}.${sourceSet.name}"
val compile = project.tasks.named(sourceSet.compileJavaTaskName, JavaCompile::class).get()
name to compile.options.allCompilerArgs.joinToString(" ") { if (it.contains(" ")) "\"$it\"" else it }
}
}
.toMap()
}

View File

@ -9,6 +9,7 @@ repositories {
}
dependencies {
implementation(libs.errorProne.plugin)
implementation(libs.kotlin.plugin)
implementation(libs.spotless)
}

View File

@ -0,0 +1,45 @@
import net.ltgt.gradle.errorprone.CheckSeverity
import net.ltgt.gradle.errorprone.errorprone
plugins {
java
id("net.ltgt.errorprone")
}
dependencies {
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
errorprone(libs.findLibrary("errorProne-core").get())
errorprone(libs.findLibrary("nullAway").get())
}
// Configure default JavaCompile tasks with our arguments.
sourceSets.all {
tasks.named(compileJavaTaskName, JavaCompile::class.java) {
options.errorprone {
check("InvalidBlockTag", CheckSeverity.OFF) // Broken by @cc.xyz
check("InvalidParam", CheckSeverity.OFF) // Broken by records.
check("InlineMeSuggester", CheckSeverity.OFF) // Minecraft uses @Deprecated liberally
// Too many false positives right now. Maybe we need an indirection for it later on.
check("ReferenceEquality",CheckSeverity.OFF)
check("UnusedVariable", CheckSeverity.OFF) // Too many false positives with records.
check("OperatorPrecedence", CheckSeverity.OFF) // For now.
check("AlreadyChecked", CheckSeverity.OFF) // Seems to be broken?
check("NonOverridingEquals", CheckSeverity.OFF) // Peripheral.equals makes this hard to avoid
check("FutureReturnValueIgnored", CheckSeverity.OFF) // Too many false positives with Netty
check("NullAway", CheckSeverity.ERROR)
option("NullAway:AnnotatedPackages", listOf("dan200.computercraft").joinToString(","))
option("NullAway:ExcludedFieldAnnotations", listOf("org.spongepowered.asm.mixin.Shadow").joinToString(","))
option("NullAway:CastToNonNullMethod", "dan200.computercraft.core.util.Nullability.assertNonNull")
option("NullAway:CheckOptionalEmptiness")
option("NullAway:AcknowledgeRestrictiveAnnotations")
}
}
}
tasks.compileTestJava {
options.errorprone {
check("NullAway", CheckSeverity.OFF)
}
}

View File

@ -17,7 +17,10 @@
<module name="TreeWalker">
<!-- Annotations -->
<module name="AnnotationLocation" />
<module name="AnnotationUseStyle" />
<module name="AnnotationUseStyle">
<!-- We want trailing commas on multiline arrays. -->
<property name="trailingArrayComma" value="ignore" />
</module>
<module name="MissingDeprecated" />
<module name="MissingOverride" />

View File

@ -30,12 +30,16 @@ junit = "5.9.1"
cctJavadoc = "1.5.2"
checkstyle = "10.3.4"
curseForgeGradle = "1.0.11"
errorProne-core = "2.14.0"
errorProne-plugin = "2.0.2"
forgeGradle = "5.1.+"
githubRelease = "2.2.12"
ideaExt = "1.1.6"
illuaminate = "0.1.0-7-g2a5a89c"
librarian = "1.+"
minotaur = "2.+"
mixinGradle = "0.7.+"
nullAway = "0.9.9"
shadow = "7.1.2"
spotless = "6.8.0"
taskTree = "2.1.0"
@ -65,19 +69,26 @@ junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", vers
# Build tools
cctJavadoc = { module = "cc.tweaked:cct-javadoc", version.ref = "cctJavadoc" }
checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" }
errorProne-annotations = { module = "com.google.errorprone:error_prone_annotations", version.ref = "errorProne-core" }
errorProne-api = { module = "com.google.errorprone:error_prone_check_api", version.ref = "errorProne-core" }
errorProne-core = { module = "com.google.errorprone:error_prone_core", version.ref = "errorProne-core" }
errorProne-plugin = { module = "net.ltgt.gradle:gradle-errorprone-plugin", version.ref = "errorProne-plugin" }
errorProne-testHelpers = { module = "com.google.errorprone:error_prone_test_helpers", version.ref = "errorProne-core" }
kotlin-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
nullAway = { module = "com.uber.nullaway:nullaway", version.ref = "nullAway" }
spotless = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" }
[plugins]
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
taskTree = { id = "com.dorongold.task-tree", version.ref = "taskTree" }
curseForgeGradle = { id = "net.darkhax.curseforgegradle", version.ref = "curseForgeGradle" }
mixinGradle = { id = "org.spongepowered.mixin", version.ref = "mixinGradle" }
minotaur = { id = "com.modrinth.minotaur", version.ref = "minotaur" }
githubRelease = { id = "com.github.breadmoirai.github-release", version.ref = "githubRelease" }
forgeGradle = { id = "net.minecraftforge.gradle", version.ref = "forgeGradle" }
githubRelease = { id = "com.github.breadmoirai.github-release", version.ref = "githubRelease" }
ideaExt = { id = "org.jetbrains.gradle.plugin.idea-ext", version.ref = "ideaExt" }
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
librarian = { id = "org.parchmentmc.librarian.forgegradle", version.ref = "librarian" }
minotaur = { id = "com.modrinth.minotaur", version.ref = "minotaur" }
mixinGradle = { id = "org.spongepowered.mixin", version.ref = "mixinGradle" }
shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }
taskTree = { id = "com.dorongold.task-tree", version.ref = "taskTree" }
[bundles]
kotlin = ["kotlin-stdlib", "kotlin-coroutines"]

View File

@ -1,6 +1,7 @@
plugins {
id("cc-tweaked.java-convention")
id("cc-tweaked.publishing")
id("cc-tweaked.errorprone")
id("cc-tweaked")
}

View File

@ -5,6 +5,7 @@
*/
package dan200.computercraft.api.filesystem;
import javax.annotation.Nullable;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.time.Instant;
@ -48,6 +49,7 @@ public boolean isOther() {
return false;
}
@Nullable
@Override
public Object fileKey() {
return null;

View File

@ -5,7 +5,6 @@
*/
package dan200.computercraft.api.filesystem;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.io.Serial;
@ -20,14 +19,14 @@ public class FileOperationException extends IOException {
@Serial
private static final long serialVersionUID = -8809108200853029849L;
private final String filename;
private final @Nullable String filename;
public FileOperationException(@Nullable String filename, @Nonnull String message) {
public FileOperationException(@Nullable String filename, String message) {
super(Objects.requireNonNull(message, "message cannot be null"));
this.filename = filename;
}
public FileOperationException(@Nonnull String message) {
public FileOperationException(String message) {
super(Objects.requireNonNull(message, "message cannot be null"));
filename = null;
}

View File

@ -7,7 +7,6 @@
import dan200.computercraft.api.peripheral.IComputerAccess;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.nio.channels.ReadableByteChannel;
import java.nio.file.attribute.BasicFileAttributes;
@ -31,7 +30,7 @@ public interface IMount {
* @return If the file exists.
* @throws IOException If an error occurs when checking the existence of the file.
*/
boolean exists(@Nonnull String path) throws IOException;
boolean exists(String path) throws IOException;
/**
* Returns whether a file with a given path is a directory or not.
@ -40,7 +39,7 @@ public interface IMount {
* @return If the file exists and is a directory
* @throws IOException If an error occurs when checking whether the file is a directory.
*/
boolean isDirectory(@Nonnull String path) throws IOException;
boolean isDirectory(String path) throws IOException;
/**
* Returns the file names of all the files in a directory.
@ -49,7 +48,7 @@ public interface IMount {
* @param contents A list of strings. Add all the file names to this list.
* @throws IOException If the file was not a directory, or could not be listed.
*/
void list(@Nonnull String path, @Nonnull List<String> contents) throws IOException;
void list(String path, List<String> contents) throws IOException;
/**
* Returns the size of a file with a given path, in bytes.
@ -58,7 +57,7 @@ public interface IMount {
* @return The size of the file, in bytes.
* @throws IOException If the file does not exist, or its size could not be determined.
*/
long getSize(@Nonnull String path) throws IOException;
long getSize(String path) throws IOException;
/**
* Opens a file with a given path, and returns an {@link ReadableByteChannel} representing its contents.
@ -69,8 +68,7 @@ public interface IMount {
* mode.
* @throws IOException If the file does not exist, or could not be opened.
*/
@Nonnull
ReadableByteChannel openForRead(@Nonnull String path) throws IOException;
ReadableByteChannel openForRead(String path) throws IOException;
/**
* Get attributes about the given file.
@ -79,8 +77,7 @@ public interface IMount {
* @return File attributes for the given file.
* @throws IOException If the file does not exist, or attributes could not be fetched.
*/
@Nonnull
default BasicFileAttributes getAttributes(@Nonnull String path) throws IOException {
default BasicFileAttributes getAttributes(String path) throws IOException {
if (!exists(path)) throw new FileOperationException(path, "No such file");
return new FileAttributes(isDirectory(path), getSize(path));
}

View File

@ -7,7 +7,6 @@
import dan200.computercraft.api.peripheral.IComputerAccess;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.channels.WritableByteChannel;
@ -31,7 +30,7 @@ public interface IWritableMount extends IMount {
* @param path A file path in normalised format, relative to the mount location. ie: "programs/mynewprograms".
* @throws IOException If the directory already exists or could not be created.
*/
void makeDirectory(@Nonnull String path) throws IOException;
void makeDirectory(String path) throws IOException;
/**
* Deletes a directory at a given path inside the virtual file system.
@ -39,7 +38,7 @@ public interface IWritableMount extends IMount {
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myoldprograms".
* @throws IOException If the file does not exist or could not be deleted.
*/
void delete(@Nonnull String path) throws IOException;
void delete(String path) throws IOException;
/**
* Opens a file with a given path, and returns an {@link OutputStream} for writing to it.
@ -49,8 +48,7 @@ public interface IWritableMount extends IMount {
* will be able to seek to arbitrary positions when using binary mode.
* @throws IOException If the file could not be opened for writing.
*/
@Nonnull
WritableByteChannel openForWrite(@Nonnull String path) throws IOException;
WritableByteChannel openForWrite(String path) throws IOException;
/**
* Opens a file with a given path, and returns an {@link OutputStream} for appending to it.
@ -60,8 +58,7 @@ public interface IWritableMount extends IMount {
* will be able to seek to arbitrary positions when using binary mode.
* @throws IOException If the file could not be opened for writing.
*/
@Nonnull
WritableByteChannel openForAppend(@Nonnull String path) throws IOException;
WritableByteChannel openForAppend(String path) throws IOException;
/**
* Get the amount of free space on the mount, in bytes. You should decrease this value as the user writes to the
@ -78,7 +75,6 @@ public interface IWritableMount extends IMount {
*
* @return The capacity of this mount, in bytes.
*/
@Nonnull
default OptionalLong getCapacity() {
return OptionalLong.empty();
}

View File

@ -9,8 +9,6 @@
import dan200.computercraft.api.peripheral.IPeripheral;
import net.minecraft.resources.ResourceLocation;
import javax.annotation.Nonnull;
/**
* A generic source of {@link LuaFunction} functions.
* <p>
@ -51,6 +49,5 @@ public interface GenericSource {
*
* @return This source's identifier.
*/
@Nonnull
ResourceLocation id();
}

View File

@ -5,7 +5,6 @@
*/
package dan200.computercraft.api.lua;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.nio.ByteBuffer;
import java.util.Map;
@ -123,7 +122,6 @@ default boolean getBoolean(int index) throws LuaException {
* @return The argument's value.
* @throws LuaException If the value is not a string.
*/
@Nonnull
default String getString(int index) throws LuaException {
var value = get(index);
if (!(value instanceof String string)) throw LuaValues.badArgumentOf(index, "string", value);
@ -137,7 +135,6 @@ default String getString(int index) throws LuaException {
* @return The argument's value. This is a <em>read only</em> buffer.
* @throws LuaException If the value is not a string.
*/
@Nonnull
default ByteBuffer getBytes(int index) throws LuaException {
return LuaValues.encode(getString(index));
}
@ -151,7 +148,6 @@ default ByteBuffer getBytes(int index) throws LuaException {
* @return The argument's value.
* @throws LuaException If the value is not a string or not a valid option for this enum.
*/
@Nonnull
default <T extends Enum<T>> T getEnum(int index, Class<T> klass) throws LuaException {
return LuaValues.checkEnum(index, klass, getString(index));
}
@ -163,7 +159,6 @@ default <T extends Enum<T>> T getEnum(int index, Class<T> klass) throws LuaExcep
* @return The argument's value.
* @throws LuaException If the value is not a table.
*/
@Nonnull
default Map<?, ?> getTable(int index) throws LuaException {
var value = get(index);
if (!(value instanceof Map)) throw LuaValues.badArgumentOf(index, "table", value);
@ -182,7 +177,6 @@ default <T extends Enum<T>> T getEnum(int index, Class<T> klass) throws LuaExcep
* @return The argument's value.
* @throws LuaException If the value is not a table.
*/
@Nonnull
default LuaTable<?, ?> getTableUnsafe(int index) throws LuaException {
return new ObjectLuaTable(getTable(index));
}
@ -194,7 +188,6 @@ default <T extends Enum<T>> T getEnum(int index, Class<T> klass) throws LuaExcep
* @return The argument's value, or {@link Optional#empty()} if not present.
* @throws LuaException If the value is not a number.
*/
@Nonnull
default Optional<Double> optDouble(int index) throws LuaException {
var value = get(index);
if (value == null) return Optional.empty();
@ -209,7 +202,6 @@ default Optional<Double> optDouble(int index) throws LuaException {
* @return The argument's value, or {@link Optional#empty()} if not present.
* @throws LuaException If the value is not a number.
*/
@Nonnull
default Optional<Integer> optInt(int index) throws LuaException {
return optLong(index).map(Long::intValue);
}
@ -289,7 +281,6 @@ default Optional<ByteBuffer> optBytes(int index) throws LuaException {
* @return The argument's value.
* @throws LuaException If the value is not a string or not a valid option for this enum.
*/
@Nonnull
default <T extends Enum<T>> Optional<T> optEnum(int index, Class<T> klass) throws LuaException {
var str = optString(index);
return str.isPresent() ? Optional.of(LuaValues.checkEnum(index, klass, str.get())) : Optional.empty();
@ -321,7 +312,6 @@ default <T extends Enum<T>> Optional<T> optEnum(int index, Class<T> klass) throw
* @return The argument's value, or {@link Optional#empty()} if not present.
* @throws LuaException If the value is not a table.
*/
@Nonnull
default Optional<LuaTable<?, ?>> optTableUnsafe(int index) throws LuaException {
var value = get(index);
if (value == null) return Optional.empty();

View File

@ -7,8 +7,6 @@
import dan200.computercraft.api.peripheral.IDynamicPeripheral;
import javax.annotation.Nonnull;
/**
* An interface for representing custom objects returned by peripherals or other Lua objects.
* <p>
@ -24,7 +22,6 @@ public interface IDynamicLuaObject {
* @return The method names this object provides.
* @see IDynamicPeripheral#getMethodNames()
*/
@Nonnull
String[] getMethodNames();
/**
@ -39,6 +36,5 @@ public interface IDynamicLuaObject {
* instruction to yield.
* @throws LuaException If the function threw an exception.
*/
@Nonnull
MethodResult callMethod(@Nonnull ILuaContext context, int method, @Nonnull IArguments arguments) throws LuaException;
MethodResult callMethod(ILuaContext context, int method, IArguments arguments) throws LuaException;
}

View File

@ -5,7 +5,6 @@
*/
package dan200.computercraft.api.lua;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
@ -23,5 +22,5 @@ public interface ILuaAPIFactory {
* @return The created API, or {@code null} if one should not be injected.
*/
@Nullable
ILuaAPI create(@Nonnull IComputerSystem computer);
ILuaAPI create(IComputerSystem computer);
}

View File

@ -5,8 +5,6 @@
*/
package dan200.computercraft.api.lua;
import javax.annotation.Nonnull;
/**
* A continuation which is called when this coroutine is resumed.
*
@ -21,6 +19,5 @@ public interface ILuaCallback {
* @return The result of this continuation. Either the result to return to the callee, or another yield.
* @throws LuaException On an error.
*/
@Nonnull
MethodResult resume(Object[] args) throws LuaException;
}

View File

@ -5,8 +5,6 @@
*/
package dan200.computercraft.api.lua;
import javax.annotation.Nonnull;
/**
* An interface passed to peripherals and {@link IDynamicLuaObject}s by computers or turtles, providing methods
* that allow the peripheral call to interface with the computer.
@ -25,7 +23,7 @@ public interface ILuaContext {
* @throws LuaException If the task could not be queued.
* @see LuaFunction#mainThread() To run functions on the main thread and return their results synchronously.
*/
long issueMainThreadTask(@Nonnull ILuaTask task) throws LuaException;
long issueMainThreadTask(ILuaTask task) throws LuaException;
/**
* Queue a task to be executed on the main server thread at the beginning of next tick, waiting for it to complete.
@ -38,8 +36,7 @@ public interface ILuaContext {
* @return The objects returned by {@code task}.
* @throws LuaException If the task could not be queued, or if the task threw an exception.
*/
@Nonnull
default MethodResult executeMainThreadTask(@Nonnull ILuaTask task) throws LuaException {
default MethodResult executeMainThreadTask(ILuaTask task) throws LuaException {
return TaskCallback.make(this, task);
}
}

View File

@ -5,8 +5,6 @@
*/
package dan200.computercraft.api.lua;
import javax.annotation.Nonnull;
/**
* A function, which can be called from Lua. If you need to return a table of functions, it is recommended to use
* an object with {@link LuaFunction} methods, or implement {@link IDynamicLuaObject}.
@ -23,6 +21,5 @@ public interface ILuaFunction {
* @return The result of calling this function.
* @throws LuaException Upon Lua errors.
*/
@Nonnull
MethodResult call(@Nonnull IArguments arguments) throws LuaException;
MethodResult call(IArguments arguments) throws LuaException;
}

View File

@ -5,7 +5,6 @@
*/
package dan200.computercraft.api.lua;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Map;
@ -96,7 +95,7 @@ default V remove(Object o) {
}
@Override
default void putAll(@Nonnull Map<? extends K, ? extends V> map) {
default void putAll(Map<? extends K, ? extends V> map) {
throw new UnsupportedOperationException("Cannot modify LuaTable");
}

View File

@ -5,7 +5,6 @@
*/
package dan200.computercraft.api.lua;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.nio.ByteBuffer;
import java.util.Map;
@ -25,8 +24,7 @@ private LuaValues() {
* @param string The string to encode.
* @return The encoded string.
*/
@Nonnull
public static ByteBuffer encode(@Nonnull String string) {
public static ByteBuffer encode(String string) {
var chars = new byte[string.length()];
for (var i = 0; i < chars.length; i++) {
var c = string.charAt(i);
@ -43,7 +41,6 @@ public static ByteBuffer encode(@Nonnull String string) {
* @param value The value to extract the type for.
* @return This value's numeric type.
*/
@Nonnull
public static String getNumericType(double value) {
if (Double.isNaN(value)) return "nan";
if (value == Double.POSITIVE_INFINITY) return "inf";
@ -58,7 +55,6 @@ public static String getNumericType(double value) {
* @return A string representation of the given value's type, in a similar format to that provided by Lua's
* {@code type} function.
*/
@Nonnull
public static String getType(@Nullable Object value) {
if (value == null) return "nil";
if (value instanceof String) return "string";
@ -76,8 +72,7 @@ public static String getType(@Nullable Object value) {
* @param actual The actual value provided for this argument.
* @return The constructed exception, which should be thrown immediately.
*/
@Nonnull
public static LuaException badArgumentOf(int index, @Nonnull String expected, @Nullable Object actual) {
public static LuaException badArgumentOf(int index, String expected, @Nullable Object actual) {
return badArgument(index, expected, getType(actual));
}
@ -89,8 +84,7 @@ public static LuaException badArgumentOf(int index, @Nonnull String expected, @N
* @param actual The provided type for this argument.
* @return The constructed exception, which should be thrown immediately.
*/
@Nonnull
public static LuaException badArgument(int index, @Nonnull String expected, @Nonnull String actual) {
public static LuaException badArgument(int index, String expected, String actual) {
return new LuaException("bad argument #" + (index + 1) + " (" + expected + " expected, got " + actual + ")");
}
@ -102,8 +96,7 @@ public static LuaException badArgument(int index, @Nonnull String expected, @Non
* @param actual The provided type for this table item.
* @return The constructed exception, which should be thrown immediately.
*/
@Nonnull
public static LuaException badTableItem(int index, @Nonnull String expected, @Nonnull String actual) {
public static LuaException badTableItem(int index, String expected, String actual) {
return new LuaException("table item #" + index + " is not " + expected + " (got " + actual + ")");
}
@ -115,8 +108,7 @@ public static LuaException badTableItem(int index, @Nonnull String expected, @No
* @param actual The provided type for this table item.
* @return The constructed exception, which should be thrown immediately.
*/
@Nonnull
public static LuaException badField(String key, @Nonnull String expected, @Nonnull String actual) {
public static LuaException badField(String key, String expected, String actual) {
return new LuaException("field " + key + " is not " + expected + " (got " + actual + ")");
}

View File

@ -7,7 +7,6 @@
import dan200.computercraft.api.peripheral.IComputerAccess;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.nio.ByteBuffer;
import java.util.Collection;
@ -23,17 +22,17 @@
public final class MethodResult {
private static final MethodResult empty = new MethodResult(null, null);
private final Object[] result;
private final ILuaCallback callback;
private final @Nullable Object[] result;
private final @Nullable ILuaCallback callback;
private final int adjust;
private MethodResult(Object[] arguments, ILuaCallback callback) {
private MethodResult(@Nullable Object[] arguments, @Nullable ILuaCallback callback) {
result = arguments;
this.callback = callback;
adjust = 0;
}
private MethodResult(Object[] arguments, ILuaCallback callback, int adjust) {
private MethodResult(@Nullable Object[] arguments, @Nullable ILuaCallback callback, int adjust) {
result = arguments;
this.callback = callback;
this.adjust = adjust;
@ -44,7 +43,6 @@ private MethodResult(Object[] arguments, ILuaCallback callback, int adjust) {
*
* @return A method result which returns immediately with no values.
*/
@Nonnull
public static MethodResult of() {
return empty;
}
@ -62,7 +60,6 @@ public static MethodResult of() {
* @param value The value to return to the calling Lua function.
* @return A method result which returns immediately with the given value.
*/
@Nonnull
public static MethodResult of(@Nullable Object value) {
return new MethodResult(new Object[]{ value }, null);
}
@ -73,7 +70,6 @@ public static MethodResult of(@Nullable Object value) {
* @param values The values to return. See {@link #of(Object)} for acceptable values.
* @return A method result which returns immediately with the given values.
*/
@Nonnull
public static MethodResult of(@Nullable Object... values) {
return values == null || values.length == 0 ? empty : new MethodResult(values, null);
}
@ -87,8 +83,7 @@ public static MethodResult of(@Nullable Object... values) {
* @return The method result which represents this yield.
* @see IComputerAccess#queueEvent(String, Object[])
*/
@Nonnull
public static MethodResult pullEvent(@Nullable String filter, @Nonnull ILuaCallback callback) {
public static MethodResult pullEvent(@Nullable String filter, ILuaCallback callback) {
Objects.requireNonNull(callback, "callback cannot be null");
return new MethodResult(new Object[]{ filter }, results -> {
if (results.length >= 1 && Objects.equals(results[0], "terminate")) {
@ -108,8 +103,7 @@ public static MethodResult pullEvent(@Nullable String filter, @Nonnull ILuaCallb
* @return The method result which represents this yield.
* @see #pullEvent(String, ILuaCallback)
*/
@Nonnull
public static MethodResult pullEventRaw(@Nullable String filter, @Nonnull ILuaCallback callback) {
public static MethodResult pullEventRaw(@Nullable String filter, ILuaCallback callback) {
Objects.requireNonNull(callback, "callback cannot be null");
return new MethodResult(new Object[]{ filter }, callback);
}
@ -123,8 +117,7 @@ public static MethodResult pullEventRaw(@Nullable String filter, @Nonnull ILuaCa
* @return The method result which represents this yield.
* @see #pullEvent(String, ILuaCallback)
*/
@Nonnull
public static MethodResult yield(@Nullable Object[] arguments, @Nonnull ILuaCallback callback) {
public static MethodResult yield(@Nullable Object[] arguments, ILuaCallback callback) {
Objects.requireNonNull(callback, "callback cannot be null");
return new MethodResult(arguments, callback);
}
@ -150,7 +143,6 @@ public int getErrorAdjust() {
* @param adjust The amount to increase the level by.
* @return The new {@link MethodResult} with an adjusted error. This has no effect on immediate results.
*/
@Nonnull
public MethodResult adjustError(int adjust) {
if (adjust < 0) throw new IllegalArgumentException("cannot adjust by a negative amount");
if (adjust == 0 || callback == null) return this;

View File

@ -5,7 +5,7 @@
*/
package dan200.computercraft.api.lua;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
@ -41,24 +41,22 @@ public boolean containsValue(Object o) {
return map.containsKey(o);
}
@Nullable
@Override
public Object get(Object o) {
return map.get(o);
}
@Nonnull
@Override
public Set<Object> keySet() {
return map.keySet();
}
@Nonnull
@Override
public Collection<Object> values() {
return map.values();
}
@Nonnull
@Override
public Set<Entry<Object, Object>> entrySet() {
return map.entrySet();

View File

@ -5,7 +5,6 @@
*/
package dan200.computercraft.api.lua;
import javax.annotation.Nonnull;
import java.util.Arrays;
final class TaskCallback implements ILuaCallback {
@ -16,7 +15,6 @@ private TaskCallback(long task) {
this.task = task;
}
@Nonnull
@Override
public MethodResult resume(Object[] response) throws LuaException {
if (response.length < 3 || !(response[1] instanceof Number) || !(response[2] instanceof Boolean)) {

View File

@ -0,0 +1,28 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
/**
* ComputerCraft's public API.
* <p>
* You probably want to start in the following places:
* <ul>
* <li>{@link dan200.computercraft.api.peripheral.IPeripheral} for registering new peripherals.</li>
* <li>
* {@link dan200.computercraft.api.lua.LuaFunction} and {@link dan200.computercraft.api.lua.IArguments} for
* adding methods to your peripheral or Lua objects.
* </li>
* </ul>
*/
@DefaultQualifier(value = NonNull.class, locations = {
TypeUseLocation.RETURN,
TypeUseLocation.PARAMETER,
TypeUseLocation.FIELD,
})
package dan200.computercraft.api;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.framework.qual.DefaultQualifier;
import org.checkerframework.framework.qual.TypeUseLocation;

View File

@ -7,8 +7,6 @@
import dan200.computercraft.api.lua.GenericSource;
import javax.annotation.Nonnull;
/**
* A {@link GenericSource} which provides methods for a peripheral.
* <p>
@ -34,7 +32,6 @@ public interface GenericPeripheral extends GenericSource {
* @return The type of this peripheral or {@link PeripheralType#untyped()}.
* @see IPeripheral#getType()
*/
@Nonnull
default PeripheralType getType() {
return PeripheralType.untyped();
}

View File

@ -12,7 +12,6 @@
import dan200.computercraft.api.lua.ILuaTask;
import dan200.computercraft.api.lua.MethodResult;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Map;
@ -36,7 +35,7 @@ public interface IComputerAccess {
* @see IMount
*/
@Nullable
default String mount(@Nonnull String desiredLocation, @Nonnull IMount mount) {
default String mount(String desiredLocation, IMount mount) {
return mount(desiredLocation, mount, getAttachmentName());
}
@ -55,7 +54,7 @@ default String mount(@Nonnull String desiredLocation, @Nonnull IMount mount) {
* @see IMount
*/
@Nullable
String mount(@Nonnull String desiredLocation, @Nonnull IMount mount, @Nonnull String driveName);
String mount(String desiredLocation, IMount mount, String driveName);
/**
* Mount a mount onto the computer's file system in a writable mode.
@ -70,7 +69,7 @@ default String mount(@Nonnull String desiredLocation, @Nonnull IMount mount) {
* @see IMount
*/
@Nullable
default String mountWritable(@Nonnull String desiredLocation, @Nonnull IWritableMount mount) {
default String mountWritable(String desiredLocation, IWritableMount mount) {
return mountWritable(desiredLocation, mount, getAttachmentName());
}
@ -87,7 +86,7 @@ default String mountWritable(@Nonnull String desiredLocation, @Nonnull IWritable
* @see #unmount(String)
* @see IMount
*/
String mountWritable(@Nonnull String desiredLocation, @Nonnull IWritableMount mount, @Nonnull String driveName);
String mountWritable(String desiredLocation, IWritableMount mount, String driveName);
/**
* Unmounts a directory previously mounted onto the computers file system by {@link #mount(String, IMount)}
@ -137,7 +136,7 @@ default String mountWritable(@Nonnull String desiredLocation, @Nonnull IWritable
* @throws NotAttachedException If the peripheral has been detached.
* @see MethodResult#pullEvent(String, ILuaCallback)
*/
void queueEvent(@Nonnull String event, @Nullable Object... arguments);
void queueEvent(String event, @Nullable Object... arguments);
/**
* Get a string, unique to the computer, by which the computer refers to this peripheral.
@ -149,7 +148,6 @@ default String mountWritable(@Nonnull String desiredLocation, @Nonnull IWritable
* @return A string unique to the computer, but not globally.
* @throws NotAttachedException If the peripheral has been detached.
*/
@Nonnull
String getAttachmentName();
/**
@ -162,7 +160,6 @@ default String mountWritable(@Nonnull String desiredLocation, @Nonnull IWritable
* @see #getAttachmentName()
* @see #getAvailablePeripheral(String)
*/
@Nonnull
Map<String, IPeripheral> getAvailablePeripherals();
/**
@ -174,7 +171,7 @@ default String mountWritable(@Nonnull String desiredLocation, @Nonnull IWritable
* @see #getAvailablePeripherals()
*/
@Nullable
IPeripheral getAvailablePeripheral(@Nonnull String name);
IPeripheral getAvailablePeripheral(String name);
/**
* Get a {@link IWorkMonitor} for tasks your peripheral might execute on the main (server) thread.
@ -190,6 +187,5 @@ default String mountWritable(@Nonnull String desiredLocation, @Nonnull IWritable
* @return The work monitor for the main thread, or {@code null} if this computer does not have one.
* @throws NotAttachedException If the peripheral has been detached.
*/
@Nonnull
IWorkMonitor getMainThreadMonitor();
}

View File

@ -7,8 +7,6 @@
import dan200.computercraft.api.lua.*;
import javax.annotation.Nonnull;
/**
* A peripheral whose methods are not known at runtime.
* <p>
@ -23,7 +21,6 @@ public interface IDynamicPeripheral extends IPeripheral {
* @return An array of strings representing method names.
* @see #callMethod
*/
@Nonnull
String[] getMethodNames();
/**
@ -47,6 +44,5 @@ public interface IDynamicPeripheral extends IPeripheral {
* arguments are supplied to your method.
* @see #getMethodNames()
*/
@Nonnull
MethodResult callMethod(@Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull IArguments arguments) throws LuaException;
MethodResult callMethod(IComputerAccess computer, ILuaContext context, int method, IArguments arguments) throws LuaException;
}

View File

@ -7,7 +7,6 @@
import dan200.computercraft.api.lua.LuaFunction;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.Set;
@ -28,7 +27,6 @@ public interface IPeripheral {
*
* @return A string identifying the type of peripheral.
*/
@Nonnull
String getType();
/**
@ -37,7 +35,6 @@ public interface IPeripheral {
* @return A collection of additional object traits.
* @see PeripheralType#getAdditionalTypes()
*/
@Nonnull
default Set<String> getAdditionalTypes() {
return Collections.emptySet();
}
@ -60,7 +57,7 @@ default Set<String> getAdditionalTypes() {
* attached to a peripheral at once.
* @see #detach
*/
default void attach(@Nonnull IComputerAccess computer) {
default void attach(IComputerAccess computer) {
}
/**
@ -80,7 +77,7 @@ default void attach(@Nonnull IComputerAccess computer) {
* attached to a peripheral at once.
* @see #attach
*/
default void detach(@Nonnull IComputerAccess computer) {
default void detach(IComputerAccess computer) {
}
/**

View File

@ -5,7 +5,6 @@
*/
package dan200.computercraft.api.peripheral;
import javax.annotation.Nonnull;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@ -48,7 +47,7 @@ public interface IWorkMonitor {
* @param time The time some task took to run
* @param unit The unit that {@code time} was measured in.
*/
void trackWork(long time, @Nonnull TimeUnit unit);
void trackWork(long time, TimeUnit unit);
/**
* Run a task if possible, and inform the monitor of how long it took.
@ -56,7 +55,7 @@ public interface IWorkMonitor {
* @param runnable The task to run.
* @return If the task was actually run (namely, {@link #canWork()} returned {@code true}).
*/
default boolean runWork(@Nonnull Runnable runnable) {
default boolean runWork(Runnable runnable) {
Objects.requireNonNull(runnable, "runnable should not be null");
if (!canWork()) return false;

View File

@ -5,7 +5,6 @@
*/
package dan200.computercraft.api.peripheral;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Collections;
@ -20,10 +19,10 @@
public final class PeripheralType {
private static final PeripheralType UNTYPED = new PeripheralType(null, Collections.emptySet());
private final String type;
private final @Nullable String type;
private final Set<String> additionalTypes;
public PeripheralType(String type, Set<String> additionalTypes) {
public PeripheralType(@Nullable String type, Set<String> additionalTypes) {
this.type = type;
this.additionalTypes = additionalTypes;
for (var item : additionalTypes) {
@ -46,7 +45,7 @@ public static PeripheralType untyped() {
* @param type The name of the type.
* @return The constructed peripheral type.
*/
public static PeripheralType ofType(@Nonnull String type) {
public static PeripheralType ofType(String type) {
checkTypeName("type cannot be null or empty");
return new PeripheralType(type, Collections.emptySet());
}
@ -58,7 +57,7 @@ public static PeripheralType ofType(@Nonnull String type) {
* @param additionalTypes Additional types, or "traits" of this peripheral. For instance, {@code "inventory"}.
* @return The constructed peripheral type.
*/
public static PeripheralType ofType(@Nonnull String type, Collection<String> additionalTypes) {
public static PeripheralType ofType(String type, Collection<String> additionalTypes) {
checkTypeName("type cannot be null or empty");
return new PeripheralType(type, getTypes(additionalTypes));
}
@ -70,7 +69,7 @@ public static PeripheralType ofType(@Nonnull String type, Collection<String> add
* @param additionalTypes Additional types, or "traits" of this peripheral. For instance, {@code "inventory"}.
* @return The constructed peripheral type.
*/
public static PeripheralType ofType(@Nonnull String type, @Nonnull String... additionalTypes) {
public static PeripheralType ofType(String type, String... additionalTypes) {
checkTypeName(type);
return new PeripheralType(type, Set.of(additionalTypes));
}
@ -91,7 +90,7 @@ public static PeripheralType ofAdditional(Collection<String> additionalTypes) {
* @param additionalTypes Additional types, or "traits" of this peripheral. For instance, {@code "inventory"}.
* @return The constructed peripheral type.
*/
public static PeripheralType ofAdditional(@Nonnull String... additionalTypes) {
public static PeripheralType ofAdditional(String... additionalTypes) {
return new PeripheralType(null, Set.of(additionalTypes));
}

View File

@ -0,0 +1,26 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.core.util;
import javax.annotation.Nullable;
public final class Nullability {
private Nullability() {
}
/**
* An alternative to {@link java.util.Objects#requireNonNull(Object)}, which should be interpreted as an assertion
* ("this case should never happen") rather than an argument check.
*
* @param object The object to check, possibly {@literal null}.
* @param <T> The type of the object to check
* @return The checked value.
*/
public static <T> T assertNonNull(@Nullable T object) {
if (object == null) throw new NullPointerException("Impossible: Should never be null");
return object;
}
}