diff --git a/.checkstyle/checkstyle.xml b/.checkstyle/checkstyle.xml index 91dc88d..f7ae8b3 100644 --- a/.checkstyle/checkstyle.xml +++ b/.checkstyle/checkstyle.xml @@ -101,7 +101,7 @@ - + diff --git a/build.gradle b/build.gradle index 0987c9a..6f6c7dd 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ indraSonatype { } dependencies { - compileOnlyApi libs.jetbrainsAnnotations + compileOnlyApi libs.jspecify implementation gradleApi() testImplementation platform(libs.junit.bom) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ce9815c..b9e2c49 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ stylecheck = "0.2.1" errorprone = "2.30.0" [libraries] -jetbrainsAnnotations = "org.jetbrains:annotations:25.0.0" +jspecify = { module = "org.jspecify:jspecify", version = "1.0.0" } # test junit-bom = { module = "org.junit:junit-bom", version.ref = "junit" } diff --git a/mammoth-test/build.gradle b/mammoth-test/build.gradle index 55c1cdd..c65d731 100644 --- a/mammoth-test/build.gradle +++ b/mammoth-test/build.gradle @@ -3,7 +3,7 @@ description = "JUnit extensions for testing Gradle plugins" dependencies { api gradleApi() api gradleTestKit() - compileOnlyApi libs.jetbrainsAnnotations + compileOnlyApi libs.jspecify api platform(libs.junit.bom) api libs.junit.api implementation libs.junit.platformCommons diff --git a/mammoth-test/src/main/java/net/kyori/mammoth/test/GradleFunctionalTestExtension.java b/mammoth-test/src/main/java/net/kyori/mammoth/test/GradleFunctionalTestExtension.java index 9823940..6a882ca 100644 --- a/mammoth-test/src/main/java/net/kyori/mammoth/test/GradleFunctionalTestExtension.java +++ b/mammoth-test/src/main/java/net/kyori/mammoth/test/GradleFunctionalTestExtension.java @@ -36,8 +36,8 @@ import java.util.List; import java.util.Optional; import java.util.stream.Stream; -import javax.annotation.Nullable; import org.gradle.util.GradleVersion; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestTemplateInvocationContext; diff --git a/mammoth-test/src/main/java/net/kyori/mammoth/test/TestContext.java b/mammoth-test/src/main/java/net/kyori/mammoth/test/TestContext.java index 361b14c..18cae4e 100644 --- a/mammoth-test/src/main/java/net/kyori/mammoth/test/TestContext.java +++ b/mammoth-test/src/main/java/net/kyori/mammoth/test/TestContext.java @@ -1,7 +1,7 @@ /* * This file is part of mammoth, licensed under the MIT License. * - * Copyright (c) 2021-2022 KyoriPowered + * Copyright (c) 2021-2024 KyoriPowered * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -37,7 +37,6 @@ import java.util.regex.Pattern; import org.gradle.testkit.runner.BuildResult; import org.gradle.testkit.runner.GradleRunner; -import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Assertions; import static java.util.Objects.requireNonNull; @@ -78,11 +77,11 @@ public final class TestContext { * @return the output directory * @since 1.1.0 */ - public @NotNull Path outputDirectory() { + public Path outputDirectory() { return this.outputDirectory; } - @NotNull String gradleVersion() { + String gradleVersion() { return this.gradleVersion; } @@ -93,7 +92,7 @@ public final class TestContext { * @throws IOException if an error occurs writing the input file to disk * @since 1.1.0 */ - public void copyInput(final @NotNull String name) throws IOException { + public void copyInput(final String name) throws IOException { this.copyInput(name, name); } @@ -105,7 +104,7 @@ public void copyInput(final @NotNull String name) throws IOException { * @throws IOException if an error occurs writing the input file to disk * @since 1.1.0 */ - public void copyInput(final @NotNull String fromName, final @NotNull String toName) throws IOException { + public void copyInput(final String fromName, final String toName) throws IOException { requireNonNull(fromName, "fromName"); requireNonNull(toName, "toName"); try (final InputStream is = this.resourceBase.getResourceAsStream(this.testName + "/in/" + fromName)) { @@ -130,7 +129,7 @@ public void copyInput(final @NotNull String fromName, final @NotNull String toNa * @throws IOException if an error occurs writing the text * @since 1.2.0 */ - public void writeText(final @NotNull String destination, final @NotNull String text) throws IOException { + public void writeText(final String destination, final String text) throws IOException { requireNonNull(destination, "destination"); requireNonNull(text, "text"); @@ -149,7 +148,7 @@ public void writeText(final @NotNull String destination, final @NotNull String t * @throws IOException if thrown while attempting to read the output file * @since 1.1.0 */ - public @NotNull String readOutput(final @NotNull String fileName) throws IOException { + public String readOutput(final String fileName) throws IOException { final StringBuilder builder = new StringBuilder(); try (final BufferedReader reader = Files.newBufferedReader(this.outputDirectory.resolve(fileName), StandardCharsets.UTF_8)) { final char[] buffer = new char[8192]; @@ -169,7 +168,7 @@ public void writeText(final @NotNull String destination, final @NotNull String t * @throws IOException if an error occurs reading the text * @since 1.2.0 */ - public void assertOutputEqualsLiteral(final @NotNull String destination, final @NotNull String text) throws IOException { + public void assertOutputEqualsLiteral(final String destination, final String text) throws IOException { requireNonNull(destination, "destination"); requireNonNull(text, "text"); @@ -188,7 +187,7 @@ public void assertOutputEqualsLiteral(final @NotNull String destination, final @ * @throws IOException if failed to read one of the files * @since 1.1.0 */ - public void assertOutputEquals(final @NotNull String resourceName, final @NotNull String fileName) throws IOException { + public void assertOutputEquals(final String resourceName, final String fileName) throws IOException { final String actualOutput = this.readOutput(fileName); final StringBuilder builder = new StringBuilder(); @@ -215,7 +214,7 @@ public void assertOutputEquals(final @NotNull String resourceName, final @NotNul * @return the new runner * @since 1.1.0 */ - public @NotNull GradleRunner runner(final @NotNull String@NotNull... extraArgs) { + public GradleRunner runner(final String... extraArgs) { final List args = new ArrayList<>(this.commonArguments.size() + extraArgs.length); args.addAll(this.commonArguments); Collections.addAll(args, extraArgs); @@ -234,7 +233,7 @@ public void assertOutputEquals(final @NotNull String resourceName, final @NotNul * @return the result of an executed build * @since 1.1.0 */ - public @NotNull BuildResult build(final @NotNull String@NotNull... extraArgs) { + public BuildResult build(final String... extraArgs) { return this.runner(extraArgs).build(); } diff --git a/mammoth-test/src/main/java/net/kyori/mammoth/test/package-info.java b/mammoth-test/src/main/java/net/kyori/mammoth/test/package-info.java index e5c9599..6c47a65 100644 --- a/mammoth-test/src/main/java/net/kyori/mammoth/test/package-info.java +++ b/mammoth-test/src/main/java/net/kyori/mammoth/test/package-info.java @@ -28,4 +28,7 @@ * annotating methods that have a parameter of either type {@link net.kyori.mammoth.test.TestContext} * or {@link org.gradle.testkit.runner.GradleRunner}.

*/ +@NullMarked package net.kyori.mammoth.test; + +import org.jspecify.annotations.NullMarked; diff --git a/src/main/java/net/kyori/mammoth/Configurable.java b/src/main/java/net/kyori/mammoth/Configurable.java index 6109ebf..29ebee8 100644 --- a/src/main/java/net/kyori/mammoth/Configurable.java +++ b/src/main/java/net/kyori/mammoth/Configurable.java @@ -1,7 +1,7 @@ /* * This file is part of mammoth, licensed under the MIT License. * - * Copyright (c) 2021-2022 KyoriPowered + * Copyright (c) 2021-2024 KyoriPowered * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,8 +24,7 @@ package net.kyori.mammoth; import org.gradle.api.Action; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; import static java.util.Objects.requireNonNull; @@ -47,7 +46,7 @@ private Configurable() { * @return the provided {@code instance} * @since 1.0.0 */ - public static @NotNull T configure(final @NotNull T instance, final @NotNull Action configureAction) { + public static T configure(final T instance, final Action configureAction) { requireNonNull(configureAction, "configureAction").execute(instance); return instance; } @@ -61,7 +60,7 @@ private Configurable() { * @return the provided {@code instance} * @since 1.0.0 */ - public static @NotNull T configureIfNonNull(final @NotNull T instance, final @Nullable Action configureAction) { + public static T configureIfNonNull(final T instance, final @Nullable Action configureAction) { if (configureAction != null) { configureAction.execute(instance); } diff --git a/src/main/java/net/kyori/mammoth/GradleCompat.java b/src/main/java/net/kyori/mammoth/GradleCompat.java index 625c5a1..cb3e397 100644 --- a/src/main/java/net/kyori/mammoth/GradleCompat.java +++ b/src/main/java/net/kyori/mammoth/GradleCompat.java @@ -1,7 +1,7 @@ /* * This file is part of mammoth, licensed under the MIT License. * - * Copyright (c) 2021-2023 KyoriPowered + * Copyright (c) 2021-2024 KyoriPowered * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,7 +28,7 @@ import org.gradle.api.Project; import org.gradle.api.provider.Provider; import org.gradle.util.GradleVersion; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; final class GradleCompat { static final boolean SHOULD_USE_CONVENTION = hasMethod(Project.class, "getConvention") && !hasMinGradleVersion("8.2"); diff --git a/src/main/java/net/kyori/mammoth/IsolatingClassLoader.java b/src/main/java/net/kyori/mammoth/IsolatingClassLoader.java index 28f681d..4225581 100644 --- a/src/main/java/net/kyori/mammoth/IsolatingClassLoader.java +++ b/src/main/java/net/kyori/mammoth/IsolatingClassLoader.java @@ -30,8 +30,7 @@ import java.util.Iterator; import java.util.Set; import org.gradle.api.file.FileCollection; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; /** * A factory for classloaders that will load classes from themselves rather than its parent where possible. @@ -54,7 +53,7 @@ private IsolatingClassLoader() { * @return the newly created loader * @since 1.4.0 */ - public static @NotNull URLClassLoader isolatingClassLoader(final @Nullable ClassLoader parent, final @NotNull URL @NotNull... urls) { + public static URLClassLoader isolatingClassLoader(final @Nullable ClassLoader parent, final URL... urls) { return new IsolatingClassLoaderImpl(urls, parent); } @@ -66,7 +65,7 @@ private IsolatingClassLoader() { * @return the newly created loader * @since 1.4.0 */ - public static @NotNull URLClassLoader isolatingClassLoader(final @Nullable ClassLoader parent, final @NotNull FileCollection files) { + public static URLClassLoader isolatingClassLoader(final @Nullable ClassLoader parent, final FileCollection files) { final Set unwrapped = files.getFiles(); final URL[] urls = new URL[unwrapped.size()]; final Iterator it = files.iterator(); diff --git a/src/main/java/net/kyori/mammoth/IsolatingClassLoaderImpl.java b/src/main/java/net/kyori/mammoth/IsolatingClassLoaderImpl.java index 6352c59..97e1a3c 100644 --- a/src/main/java/net/kyori/mammoth/IsolatingClassLoaderImpl.java +++ b/src/main/java/net/kyori/mammoth/IsolatingClassLoaderImpl.java @@ -28,25 +28,24 @@ import java.net.URLClassLoader; import java.util.Enumeration; import java.util.NoSuchElementException; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; final class IsolatingClassLoaderImpl extends URLClassLoader { static { ClassLoader.registerAsParallelCapable(); } - private final ClassLoader parent; + private final @Nullable ClassLoader parent; // todo: maybe add transformer function (UnaryOperator)? just for fun // todo: add a filter - IsolatingClassLoaderImpl(final URL[] urls, final ClassLoader parent) { + IsolatingClassLoaderImpl(final URL[] urls, final @Nullable ClassLoader parent) { super(urls, parent); this.parent = parent; } @Override - protected @Nullable Class loadClass(final @NotNull String name, final boolean resolve) throws ClassNotFoundException { + protected @Nullable Class loadClass(final String name, final boolean resolve) throws ClassNotFoundException { synchronized (this.getClassLoadingLock(name)) { Class result = this.findLoadedClass(name); if (result == null) { @@ -78,7 +77,7 @@ final class IsolatingClassLoaderImpl extends URLClassLoader { } @Override - public @NotNull Enumeration getResources(final String name) throws IOException { + public Enumeration getResources(final String name) throws IOException { return new Enumeration() { @Nullable Enumeration active = IsolatingClassLoaderImpl.this.findResources(name); @Nullable Enumeration staged = IsolatingClassLoaderImpl.this.parent == null @@ -102,7 +101,7 @@ public boolean hasMoreElements() { } @Override - public @NotNull URL nextElement() { + public URL nextElement() { final @Nullable Enumeration component = this.nextComponent(); if (component == null) { throw new NoSuchElementException(); diff --git a/src/main/java/net/kyori/mammoth/ProjectOrSettingsPlugin.java b/src/main/java/net/kyori/mammoth/ProjectOrSettingsPlugin.java index 0566380..6917da0 100644 --- a/src/main/java/net/kyori/mammoth/ProjectOrSettingsPlugin.java +++ b/src/main/java/net/kyori/mammoth/ProjectOrSettingsPlugin.java @@ -1,7 +1,7 @@ /* * This file is part of mammoth, licensed under the MIT License. * - * Copyright (c) 2021-2022 KyoriPowered + * Copyright (c) 2021-2024 KyoriPowered * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,8 +32,7 @@ import org.gradle.api.plugins.PluginContainer; import org.gradle.api.tasks.TaskContainer; import org.gradle.util.GradleVersion; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; /** * A plugin that can be applied to either a {@link Project} or {@link Settings}. @@ -42,7 +41,7 @@ */ public interface ProjectOrSettingsPlugin extends Plugin { @Override - default void apply(final @NotNull Object target) { + default void apply(final Object target) { if (target instanceof Project) { final Project project = (Project) target; GradleCompat.requireMinimumVersion(this.minimumGradleVersion(), this, project.getDisplayName()); @@ -71,10 +70,10 @@ default void apply(final @NotNull Object target) { * @since 1.3.0 */ void applyToProject( - final @NotNull Project target, - final @NotNull PluginContainer plugins, - final @NotNull ExtensionContainer extensions, - final @NotNull TaskContainer tasks + final Project target, + final PluginContainer plugins, + final ExtensionContainer extensions, + final TaskContainer tasks ); /** @@ -86,9 +85,9 @@ void applyToProject( * @since 1.3.0 */ void applyToSettings( - final @NotNull Settings target, - final @NotNull PluginContainer plugins, - final @NotNull ExtensionContainer extensions + final Settings target, + final PluginContainer plugins, + final ExtensionContainer extensions ); /** @@ -108,7 +107,7 @@ void applyToSettings( * @return whether the Settings that created the provided project has this plugin applied * @since 1.3.0 */ - default boolean isAppliedToSettingsOf(final @NotNull Project project) { + default boolean isAppliedToSettingsOf(final Project project) { return project.getGradle().getPlugins().hasPlugin(this.getClass()); } } diff --git a/src/main/java/net/kyori/mammoth/ProjectPlugin.java b/src/main/java/net/kyori/mammoth/ProjectPlugin.java index 92f8d34..e8c1bfc 100644 --- a/src/main/java/net/kyori/mammoth/ProjectPlugin.java +++ b/src/main/java/net/kyori/mammoth/ProjectPlugin.java @@ -1,7 +1,7 @@ /* * This file is part of mammoth, licensed under the MIT License. * - * Copyright (c) 2021-2023 KyoriPowered + * Copyright (c) 2021-2024 KyoriPowered * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,8 +31,7 @@ import org.gradle.api.plugins.PluginContainer; import org.gradle.api.tasks.TaskContainer; import org.gradle.util.GradleVersion; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; /** * A more friendly interface for creating a {@link Plugin} that operates on a {@link Project}. @@ -44,7 +43,7 @@ public interface ProjectPlugin extends Plugin { @Override @SuppressWarnings("deprecation") // workaround - default void apply(final @NotNull Project project) { + default void apply(final Project project) { // Check version GradleCompat.requireMinimumVersion(this.minimumGradleVersion(), this, project.getDisplayName()); @@ -79,11 +78,11 @@ default void apply(final @NotNull Project project) { */ @Deprecated default void apply( - final @NotNull Project project, - final @NotNull PluginContainer plugins, - final @NotNull ExtensionContainer extensions, - final @NotNull Convention convention, - final @NotNull TaskContainer tasks + final Project project, + final PluginContainer plugins, + final ExtensionContainer extensions, + final Convention convention, + final TaskContainer tasks ) { this.apply(project, plugins, extensions, tasks); } @@ -98,10 +97,10 @@ default void apply( * @since 1.1.0 */ default void apply( - final @NotNull Project project, - final @NotNull PluginContainer plugins, - final @NotNull ExtensionContainer extensions, - final @NotNull TaskContainer tasks + final Project project, + final PluginContainer plugins, + final ExtensionContainer extensions, + final TaskContainer tasks ) { throw new GradleException("The plugin in class " + this.getClass() + " has not been updated" + "to override the non-Convention apply method in ProjectPlugin!"); diff --git a/src/main/java/net/kyori/mammoth/Properties.java b/src/main/java/net/kyori/mammoth/Properties.java index 92cb09f..c0f8817 100644 --- a/src/main/java/net/kyori/mammoth/Properties.java +++ b/src/main/java/net/kyori/mammoth/Properties.java @@ -1,7 +1,7 @@ /* * This file is part of mammoth, licensed under the MIT License. * - * Copyright (c) 2021-2022 KyoriPowered + * Copyright (c) 2021-2024 KyoriPowered * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,7 +25,6 @@ import org.gradle.api.provider.HasConfigurableValue; import org.gradle.api.provider.Provider; -import org.jetbrains.annotations.NotNull; /** * Helpers for working with properties. @@ -47,7 +46,7 @@ private Properties() { * @since 1.1.0 */ @SuppressWarnings("deprecation") - public static @NotNull Provider forUseAtConfigurationTime(final @NotNull Provider provider) { + public static Provider forUseAtConfigurationTime(final Provider provider) { if (GradleCompat.HAS_FOR_USE_AT_CONFIGURATION_TIME) { return provider.forUseAtConfigurationTime(); } else { @@ -63,7 +62,7 @@ private Properties() { * @return the property * @since 1.0.0 */ - public static @NotNull T finalized(final @NotNull T property) { + public static T finalized(final T property) { property.finalizeValue(); return property; } @@ -76,7 +75,7 @@ private Properties() { * @return the property * @since 1.0.0 */ - public static @NotNull T finalizedOnRead(final @NotNull T property) { + public static T finalizedOnRead(final T property) { property.finalizeValueOnRead(); return property; } @@ -89,7 +88,7 @@ private Properties() { * @return the property * @since 1.0.0 */ - public static @NotNull T changesDisallowed(final @NotNull T property) { + public static T changesDisallowed(final T property) { property.disallowChanges(); return property; } diff --git a/src/main/java/net/kyori/mammoth/package-info.java b/src/main/java/net/kyori/mammoth/package-info.java index ab41c5f..067f123 100644 --- a/src/main/java/net/kyori/mammoth/package-info.java +++ b/src/main/java/net/kyori/mammoth/package-info.java @@ -24,4 +24,7 @@ /** * Helpers for developing Gradle plugins. */ +@NullMarked package net.kyori.mammoth; + +import org.jspecify.annotations.NullMarked; diff --git a/src/test/java/net/kyori/mammoth/ProjectPluginTest.java b/src/test/java/net/kyori/mammoth/ProjectPluginTest.java index 5c71687..56ed875 100644 --- a/src/test/java/net/kyori/mammoth/ProjectPluginTest.java +++ b/src/test/java/net/kyori/mammoth/ProjectPluginTest.java @@ -1,7 +1,7 @@ /* * This file is part of mammoth, licensed under the MIT License. * - * Copyright (c) 2021-2023 KyoriPowered + * Copyright (c) 2021-2024 KyoriPowered * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,8 +31,7 @@ import org.gradle.api.tasks.TaskContainer; import org.gradle.testfixtures.ProjectBuilder; import org.gradle.util.GradleVersion; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; @@ -44,7 +43,7 @@ class ProjectPluginTest { static class ProjectPluginFailing implements ProjectPlugin { @Override - public void apply(final @NotNull Project project, final @NotNull PluginContainer plugins, final @NotNull ExtensionContainer extensions, final @NotNull TaskContainer tasks) { + public void apply(final Project project, final PluginContainer plugins, final ExtensionContainer extensions, final TaskContainer tasks) { // no-op } @@ -57,7 +56,7 @@ public void apply(final @NotNull Project project, final @NotNull PluginContainer static class ProjectPluginSuccessful implements ProjectPlugin { @Override - public void apply(final @NotNull Project project, final @NotNull PluginContainer plugins, final @NotNull ExtensionContainer extensions, final @NotNull TaskContainer tasks) { + public void apply(final Project project, final PluginContainer plugins, final ExtensionContainer extensions, final TaskContainer tasks) { // no-op }