1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-07-04 11:02:54 +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 cc.tweaked.gradle.*
import net.darkhax.curseforgegradle.TaskPublishCurseForge import net.darkhax.curseforgegradle.TaskPublishCurseForge
import net.minecraftforge.gradle.common.util.RunConfig import net.minecraftforge.gradle.common.util.RunConfig
import org.jetbrains.gradle.ext.compiler
import org.jetbrains.gradle.ext.settings
plugins { plugins {
// Build // Build
@ -14,6 +16,7 @@ plugins {
alias(libs.plugins.minotaur) alias(libs.plugins.minotaur)
// Utility // Utility
alias(libs.plugins.taskTree) alias(libs.plugins.taskTree)
alias(libs.plugins.ideaExt)
id("cc-tweaked.illuaminate") id("cc-tweaked.illuaminate")
id("cc-tweaked.node") 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 { dependencies {
implementation(libs.errorProne.plugin)
implementation(libs.kotlin.plugin) implementation(libs.kotlin.plugin)
implementation(libs.spotless) 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"> <module name="TreeWalker">
<!-- Annotations --> <!-- Annotations -->
<module name="AnnotationLocation" /> <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="MissingDeprecated" />
<module name="MissingOverride" /> <module name="MissingOverride" />

View File

@ -30,12 +30,16 @@ junit = "5.9.1"
cctJavadoc = "1.5.2" cctJavadoc = "1.5.2"
checkstyle = "10.3.4" checkstyle = "10.3.4"
curseForgeGradle = "1.0.11" curseForgeGradle = "1.0.11"
errorProne-core = "2.14.0"
errorProne-plugin = "2.0.2"
forgeGradle = "5.1.+" forgeGradle = "5.1.+"
githubRelease = "2.2.12" githubRelease = "2.2.12"
ideaExt = "1.1.6"
illuaminate = "0.1.0-7-g2a5a89c" illuaminate = "0.1.0-7-g2a5a89c"
librarian = "1.+" librarian = "1.+"
minotaur = "2.+" minotaur = "2.+"
mixinGradle = "0.7.+" mixinGradle = "0.7.+"
nullAway = "0.9.9"
shadow = "7.1.2" shadow = "7.1.2"
spotless = "6.8.0" spotless = "6.8.0"
taskTree = "2.1.0" taskTree = "2.1.0"
@ -65,19 +69,26 @@ junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", vers
# Build tools # Build tools
cctJavadoc = { module = "cc.tweaked:cct-javadoc", version.ref = "cctJavadoc" } cctJavadoc = { module = "cc.tweaked:cct-javadoc", version.ref = "cctJavadoc" }
checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" } 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" } 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" } spotless = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" }
[plugins] [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" } 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" } 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" } 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" } shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }
taskTree = { id = "com.dorongold.task-tree", version.ref = "taskTree" }
[bundles] [bundles]
kotlin = ["kotlin-stdlib", "kotlin-coroutines"] kotlin = ["kotlin-stdlib", "kotlin-coroutines"]

View File

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

View File

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

View File

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

View File

@ -7,7 +7,6 @@ package dan200.computercraft.api.filesystem;
import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.peripheral.IComputerAccess;
import javax.annotation.Nonnull;
import java.io.IOException; import java.io.IOException;
import java.nio.channels.ReadableByteChannel; import java.nio.channels.ReadableByteChannel;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
@ -31,7 +30,7 @@ public interface IMount {
* @return If the file exists. * @return If the file exists.
* @throws IOException If an error occurs when checking the existence of the file. * @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. * 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 * @return If the file exists and is a directory
* @throws IOException If an error occurs when checking whether the file 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. * 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. * @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. * @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. * 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. * @return The size of the file, in bytes.
* @throws IOException If the file does not exist, or its size could not be determined. * @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. * Opens a file with a given path, and returns an {@link ReadableByteChannel} representing its contents.
@ -69,8 +68,7 @@ public interface IMount {
* mode. * mode.
* @throws IOException If the file does not exist, or could not be opened. * @throws IOException If the file does not exist, or could not be opened.
*/ */
@Nonnull ReadableByteChannel openForRead(String path) throws IOException;
ReadableByteChannel openForRead(@Nonnull String path) throws IOException;
/** /**
* Get attributes about the given file. * Get attributes about the given file.
@ -79,8 +77,7 @@ public interface IMount {
* @return File attributes for the given file. * @return File attributes for the given file.
* @throws IOException If the file does not exist, or attributes could not be fetched. * @throws IOException If the file does not exist, or attributes could not be fetched.
*/ */
@Nonnull default BasicFileAttributes getAttributes(String path) throws IOException {
default BasicFileAttributes getAttributes(@Nonnull String path) throws IOException {
if (!exists(path)) throw new FileOperationException(path, "No such file"); if (!exists(path)) throw new FileOperationException(path, "No such file");
return new FileAttributes(isDirectory(path), getSize(path)); return new FileAttributes(isDirectory(path), getSize(path));
} }

View File

@ -7,7 +7,6 @@ package dan200.computercraft.api.filesystem;
import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.peripheral.IComputerAccess;
import javax.annotation.Nonnull;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.channels.WritableByteChannel; 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". * @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. * @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. * 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". * @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. * @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. * 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. * will be able to seek to arbitrary positions when using binary mode.
* @throws IOException If the file could not be opened for writing. * @throws IOException If the file could not be opened for writing.
*/ */
@Nonnull WritableByteChannel openForWrite(String path) throws IOException;
WritableByteChannel openForWrite(@Nonnull String path) throws IOException;
/** /**
* Opens a file with a given path, and returns an {@link OutputStream} for appending to it. * 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. * will be able to seek to arbitrary positions when using binary mode.
* @throws IOException If the file could not be opened for writing. * @throws IOException If the file could not be opened for writing.
*/ */
@Nonnull WritableByteChannel openForAppend(String path) throws IOException;
WritableByteChannel openForAppend(@Nonnull 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 * 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. * @return The capacity of this mount, in bytes.
*/ */
@Nonnull
default OptionalLong getCapacity() { default OptionalLong getCapacity() {
return OptionalLong.empty(); return OptionalLong.empty();
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,8 +5,6 @@
*/ */
package dan200.computercraft.api.lua; package dan200.computercraft.api.lua;
import javax.annotation.Nonnull;
/** /**
* An interface passed to peripherals and {@link IDynamicLuaObject}s by computers or turtles, providing methods * 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. * 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. * @throws LuaException If the task could not be queued.
* @see LuaFunction#mainThread() To run functions on the main thread and return their results synchronously. * @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. * 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}. * @return The objects returned by {@code task}.
* @throws LuaException If the task could not be queued, or if the task threw an exception. * @throws LuaException If the task could not be queued, or if the task threw an exception.
*/ */
@Nonnull default MethodResult executeMainThreadTask(ILuaTask task) throws LuaException {
default MethodResult executeMainThreadTask(@Nonnull ILuaTask task) throws LuaException {
return TaskCallback.make(this, task); return TaskCallback.make(this, task);
} }
} }

View File

@ -5,8 +5,6 @@
*/ */
package dan200.computercraft.api.lua; 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 * 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}. * an object with {@link LuaFunction} methods, or implement {@link IDynamicLuaObject}.
@ -23,6 +21,5 @@ public interface ILuaFunction {
* @return The result of calling this function. * @return The result of calling this function.
* @throws LuaException Upon Lua errors. * @throws LuaException Upon Lua errors.
*/ */
@Nonnull MethodResult call(IArguments arguments) throws LuaException;
MethodResult call(@Nonnull IArguments arguments) throws LuaException;
} }

View File

@ -5,7 +5,6 @@
*/ */
package dan200.computercraft.api.lua; package dan200.computercraft.api.lua;
import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Map; import java.util.Map;
@ -96,7 +95,7 @@ public interface LuaTable<K, V> extends Map<K, V> {
} }
@Override @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"); throw new UnsupportedOperationException("Cannot modify LuaTable");
} }

View File

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

View File

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

View File

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

View File

@ -5,7 +5,6 @@
*/ */
package dan200.computercraft.api.lua; package dan200.computercraft.api.lua;
import javax.annotation.Nonnull;
import java.util.Arrays; import java.util.Arrays;
final class TaskCallback implements ILuaCallback { final class TaskCallback implements ILuaCallback {
@ -16,7 +15,6 @@ final class TaskCallback implements ILuaCallback {
this.task = task; this.task = task;
} }
@Nonnull
@Override @Override
public MethodResult resume(Object[] response) throws LuaException { public MethodResult resume(Object[] response) throws LuaException {
if (response.length < 3 || !(response[1] instanceof Number) || !(response[2] instanceof Boolean)) { 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 @@ package dan200.computercraft.api.peripheral;
import dan200.computercraft.api.lua.GenericSource; import dan200.computercraft.api.lua.GenericSource;
import javax.annotation.Nonnull;
/** /**
* A {@link GenericSource} which provides methods for a peripheral. * A {@link GenericSource} which provides methods for a peripheral.
* <p> * <p>
@ -34,7 +32,6 @@ public interface GenericPeripheral extends GenericSource {
* @return The type of this peripheral or {@link PeripheralType#untyped()}. * @return The type of this peripheral or {@link PeripheralType#untyped()}.
* @see IPeripheral#getType() * @see IPeripheral#getType()
*/ */
@Nonnull
default PeripheralType getType() { default PeripheralType getType() {
return PeripheralType.untyped(); return PeripheralType.untyped();
} }

View File

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

View File

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

View File

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

View File

@ -5,7 +5,6 @@
*/ */
package dan200.computercraft.api.peripheral; package dan200.computercraft.api.peripheral;
import javax.annotation.Nonnull;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -48,7 +47,7 @@ public interface IWorkMonitor {
* @param time The time some task took to run * @param time The time some task took to run
* @param unit The unit that {@code time} was measured in. * @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. * 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. * @param runnable The task to run.
* @return If the task was actually run (namely, {@link #canWork()} returned {@code true}). * @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"); Objects.requireNonNull(runnable, "runnable should not be null");
if (!canWork()) return false; if (!canWork()) return false;

View File

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