Static code analysis (#1844)

* StringBuffer (Java 5) may be declared as StringBuilder

* Replace map with flatMap

* Use instanceof naming

* No need to specify paramter types.

* Remove verbose code

* Fix JavaDoc issues

* Make internal class a record.

* Remove unused import.

* Make internal class a record.

* Made internal class a record.

* Removed unused import

* Fix typos

* Fix typo in test.
This commit is contained in:
tastybento 2021-08-29 18:17:38 -07:00 committed by GitHub
parent 9dc4ebc2d1
commit 23857501f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 56 additions and 157 deletions

View File

@ -263,7 +263,7 @@ public class BentoBox extends JavaPlugin {
}
private void fireCriticalError(String message, String error) {
logError("*****************CRITIAL ERROR!******************");
logError("*****************CRITICAL ERROR!******************");
logError(message);
logError(error + " Disabling BentoBox...");
logError("*************************************************");

View File

@ -61,9 +61,9 @@ public abstract class ConfirmableCommand extends CompositeCommand {
public void askConfirmation(User user, String message, Runnable confirmed) {
// Check for pending confirmations
if (toBeConfirmed.containsKey(user)) {
if (toBeConfirmed.get(user).getTopLabel().equals(getTopLabel()) && toBeConfirmed.get(user).getLabel().equalsIgnoreCase(getLabel())) {
toBeConfirmed.get(user).getTask().cancel();
Bukkit.getScheduler().runTask(getPlugin(), toBeConfirmed.get(user).getRunnable());
if (toBeConfirmed.get(user).topLabel().equals(getTopLabel()) && toBeConfirmed.get(user).label().equalsIgnoreCase(getLabel())) {
toBeConfirmed.get(user).task().cancel();
Bukkit.getScheduler().runTask(getPlugin(), toBeConfirmed.get(user).runnable());
toBeConfirmed.remove(user);
return;
} else {
@ -97,51 +97,9 @@ public abstract class ConfirmableCommand extends CompositeCommand {
}
/**
* Holds the data to run once the confirmation is given
* @author tastybento
* Record to hold the data to run once the confirmation is given
*
*/
private class Confirmer {
private final String topLabel;
private final String label;
private final Runnable runnable;
private final BukkitTask task;
/**
* @param label - command label
* @param runnable - runnable to run when confirmed
* @param task - task ID to cancel when confirmed
*/
Confirmer(String topLabel, String label, Runnable runnable, BukkitTask task) {
this.topLabel = topLabel;
this.label = label;
this.runnable = runnable;
this.task = task;
}
/**
* @return the topLabel
*/
public String getTopLabel() {
return topLabel;
}
/**
* @return the label
*/
public String getLabel() {
return label;
}
/**
* @return the runnable
*/
public Runnable getRunnable() {
return runnable;
}
/**
* @return the task
*/
public BukkitTask getTask() {
return task;
}
}
private record Confirmer (String topLabel, String label, Runnable runnable, BukkitTask task) { }
}

View File

@ -32,14 +32,14 @@ public abstract class DelayedTeleportCommand extends CompositeCommand implements
public void onPlayerMove(PlayerMoveEvent e) {
UUID uuid = e.getPlayer().getUniqueId();
// Only check x,y,z
if (toBeMonitored.containsKey(uuid) && !e.getTo().toVector().equals(toBeMonitored.get(uuid).getLocation().toVector())) {
if (toBeMonitored.containsKey(uuid) && !e.getTo().toVector().equals(toBeMonitored.get(uuid).location().toVector())) {
moved(uuid);
}
}
private void moved(UUID uuid) {
// Player moved
toBeMonitored.get(uuid).getTask().cancel();
toBeMonitored.get(uuid).task().cancel();
toBeMonitored.remove(uuid);
// Player has another outstanding confirmation request that will now be cancelled
User.getInstance(uuid).notify("commands.delay.moved-so-command-cancelled");
@ -103,7 +103,7 @@ public abstract class DelayedTeleportCommand extends CompositeCommand implements
UUID uuid = user.getUniqueId();
if (toBeMonitored.containsKey(uuid)) {
// A double request - clear out the old one
toBeMonitored.get(uuid).getTask().cancel();
toBeMonitored.get(uuid).task().cancel();
toBeMonitored.remove(uuid);
// Player has another outstanding confirmation request that will now be cancelled
user.sendMessage("commands.delay.previous-command-cancelled");
@ -116,7 +116,7 @@ public abstract class DelayedTeleportCommand extends CompositeCommand implements
user.sendMessage("commands.delay.stand-still", "[seconds]", String.valueOf(getSettings().getDelayTime()));
// Set up the run task
BukkitTask task = Bukkit.getScheduler().runTaskLater(getPlugin(), () -> {
Bukkit.getScheduler().runTask(getPlugin(), toBeMonitored.get(uuid).getRunnable());
Bukkit.getScheduler().runTask(getPlugin(), toBeMonitored.get(uuid).runnable());
toBeMonitored.remove(uuid);
}, getPlugin().getSettings().getDelayTime() * 20L);
@ -135,42 +135,8 @@ public abstract class DelayedTeleportCommand extends CompositeCommand implements
/**
* Holds the data to run once the confirmation is given
* @author tastybento
*
*/
private class DelayedCommand {
private final Runnable runnable;
private final BukkitTask task;
private final Location location;
/**
* @param runnable - runnable to run when confirmed
* @param task - task ID to cancel when confirmed
* @param location - location
*/
DelayedCommand(Runnable runnable, BukkitTask task, Location location) {
this.runnable = runnable;
this.task = task;
this.location = location;
}
/**
* @return the runnable
*/
public Runnable getRunnable() {
return runnable;
}
/**
* @return the task
*/
public BukkitTask getTask() {
return task;
}
/**
* @return the location
*/
public Location getLocation() {
return location;
}
}
private record DelayedCommand(Runnable runnable, BukkitTask task, Location location) {}
}

View File

@ -61,7 +61,7 @@ public abstract class DefaultAdminCommand extends CompositeCommand {
new AdminTeamDisbandCommand(this);
new AdminTeamSetownerCommand(this);
new AdminTeamFixCommand(this);
// Schems
// Blueprints
new AdminBlueprintCommand(this);
// Register/unregister islands
new AdminRegisterCommand(this);
@ -96,7 +96,7 @@ public abstract class DefaultAdminCommand extends CompositeCommand {
/**
* Defines what will be executed when this command is run.
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#execute(User, String, List<String>)
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#execute(User, String, List)
*/
@Override
public boolean execute(User user, String label, List<String> args) {

View File

@ -219,7 +219,7 @@ public class Flag implements Comparable<Flag> {
/**
* Set the original status of this flag for locations outside of island spaces.
* May be overriden by the the setting for this world.
* May be overridden by the setting for this world.
* Does not affect subflags.
* @param defaultSetting - true means it is allowed. false means it is not allowed
*/
@ -399,7 +399,6 @@ public class Flag implements Comparable<Flag> {
case PROTECTION -> createProtectionFlag(plugin, user, island, pib).build();
case SETTING -> createSettingFlag(user, island, pib).build();
case WORLD_SETTING -> createWorldSettingFlag(user, pib).build();
default -> pib.build();
};
}

View File

@ -2,7 +2,7 @@
* This package contains the API for protection and settings flags
*
* <p>
* New flags should usee the Flag.Builder to create a flag. Listeners for flag related events should
* New flags should use the Flag.Builder to create a flag. Listeners for flag related events should
* extend the abstract FlagListener class.
* </p>
* <p>

View File

@ -9,7 +9,7 @@ import com.google.common.cache.LoadingCache;
/**
* Utilities class that helps to avoid spamming the User with potential repeated messages
* @author Poslovitch
* @author Poslovitch, tastybento
*/
public class Notifier {
@ -18,6 +18,8 @@ public class Notifier {
*/
private static final int NOTIFICATION_DELAY = 4;
private record Notification(String message, long time) {}
private final LoadingCache<User, Notification> notificationCache = CacheBuilder.newBuilder()
.expireAfterAccess(NOTIFICATION_DELAY, TimeUnit.SECONDS)
.maximumSize(500)
@ -28,7 +30,7 @@ public class Notifier {
return new Notification(null, 0);
}
}
);
);
/**
* Sends message to a user only if the message hasn't been sent recently
@ -41,7 +43,7 @@ public class Notifier {
Notification lastNotification = notificationCache.get(user);
long now = System.currentTimeMillis();
if (now >= lastNotification.getTime() + (NOTIFICATION_DELAY * 1000) || !message.equals(lastNotification.getMessage())) {
if (now >= lastNotification.time() + (NOTIFICATION_DELAY * 1000) || !message.equals(lastNotification.message())) {
notificationCache.put(user, new Notification(message, now));
user.sendRawMessage(message);
return true;
@ -52,21 +54,4 @@ public class Notifier {
}
}
private class Notification {
private final String message;
private final long time;
private Notification(String message, long time) {
this.message = message;
this.time = time;
}
public String getMessage() {
return message;
}
public long getTime() {
return time;
}
}
}

View File

@ -1,5 +1,5 @@
/**
* The package cotnains non-API commands for BentoBox itself.
* The package contains non-API commands for BentoBox itself.
*
* @author tastybento
*

View File

@ -1,7 +1,7 @@
/**
* These are GSON adapters used to serialize and deserialize various data types.
* <p>
* The {@link world.bentobox.bentobox.database.json.adapters#BukkitObjectTypeAdapter}
* The {@link world.bentobox.bentobox.database.json.adapters.BukkitObjectTypeAdapter}
* is a catch-all adapter that uses the built-in Bukkit serialization capabilities. Before
* we knew about this, there were other ones built, like for Location, that have to remain
* for backwards compatibility reasons.

View File

@ -7,8 +7,8 @@
* and the ability to transition between them.
* </p>
* <p>
* Storage of POJOs is done via GSON, i.e, the object is serialized and then stored. Each ddata object must
* implement the DataObject interface, which requires a uniquId field. This is what is used for indexing
* Storage of POJOs is done via GSON, i.e, the object is serialized and then stored. Each data object must
* implement the DataObject interface, which requires a uniqueId field. This is what is used for indexing
* and finding.
* </p>
* <p>

View File

@ -151,10 +151,9 @@ public class YamlDatabaseConnector implements DatabaseConnector {
for (Entry<String, String> e : commentMap.entrySet()) {
if (nextLine.contains(e.getKey())) {
// We want the comment to start at the same level as the entry
StringBuilder commentLine = new StringBuilder();
commentLine.append(" ".repeat(Math.max(0, nextLine.indexOf(e.getKey()))));
commentLine.append(e.getValue());
nextLine = commentLine.toString();
String commentLine = " ".repeat(Math.max(0, nextLine.indexOf(e.getKey()))) +
e.getValue();
nextLine = commentLine;
break;
}
}

View File

@ -554,20 +554,20 @@ public class YamlDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
}
// UUID has it's own serialization, that is not picked up automatically
if (object instanceof UUID) {
return ((UUID)object).toString();
return object.toString();
}
// Only the world name is needed for worlds
if (object instanceof World) {
return ((World)object).getName();
if (object instanceof World w) {
return w.getName();
}
// Location
if (object instanceof Location) {
return Util.getStringLocation((Location)object);
if (object instanceof Location l) {
return Util.getStringLocation(l);
}
// Enums
if (object instanceof Enum) {
if (object instanceof Enum<?> e) {
//Custom enums are a child of the Enum class. Just get the names of each one.
return ((Enum<?>)object).name();
return e.name();
}
return object;
}

View File

@ -284,7 +284,6 @@ public class LangUtilsHook extends Hook {
case LUCK -> "Potion of Luck";
case TURTLE_MASTER -> "Potion of the Turtle Master";
case SLOW_FALLING -> "Potion of Slow Falling";
default -> Util.prettifyText(potionType.name());
};
}
@ -322,7 +321,6 @@ public class LangUtilsHook extends Hook {
case LUCK -> "Splash Potion of Luck";
case TURTLE_MASTER -> "Splash Potion of the Turtle Master";
case SLOW_FALLING -> "Splash Potion of Slow Falling";
default -> Util.prettifyText(potionType.name());
};
}
@ -359,7 +357,6 @@ public class LangUtilsHook extends Hook {
case LUCK -> "Lingering Potion of Luck";
case TURTLE_MASTER -> "Lingering Potion of the Turtle Master";
case SLOW_FALLING -> "Lingering Potion of Slow Falling";
default -> Util.prettifyText(potionType.name());
};
}
@ -394,7 +391,6 @@ public class LangUtilsHook extends Hook {
case LUCK -> "Arrow of Luck";
case TURTLE_MASTER -> "Arrow of the Turtle Master";
case SLOW_FALLING -> "Arrow of Slow Falling";
default -> Util.prettifyText(potionType.name());
};
}

View File

@ -126,7 +126,7 @@ public class JoinLeaveListener implements Listener {
// - abort on logout is false
// - abort on logout is true && user is online
if (!plugin.getIWM().isCreateIslandOnFirstLoginAbortOnLogout(w) || user.isOnline()){
plugin.getIWM().getAddon(w).flatMap(addon -> addon.getPlayerCommand().map(command -> command.getSubCommand("create").orElse(null)))
plugin.getIWM().getAddon(w).flatMap(addon -> addon.getPlayerCommand().flatMap(command -> command.getSubCommand("create")))
.ifPresent(command -> command.execute(user, "create", Collections.singletonList(BlueprintsManager.DEFAULT_BUNDLE_NAME)));
}
};

View File

@ -1,9 +1,9 @@
package world.bentobox.bentobox.listeners;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import org.bukkit.ChatColor;
import org.bukkit.entity.HumanEntity;
@ -97,8 +97,8 @@ public class PanelListenerManager implements Listener {
*/
public static void closeAllPanels() {
// Use stream clones to avoid concurrent modification exceptions
openPanels.values().stream().collect(Collectors.toList()).forEach(p ->
p.getInventory().getViewers().stream().collect(Collectors.toList()).forEach(HumanEntity::closeInventory));
new ArrayList<>(openPanels.values()).forEach(p ->
new ArrayList<>(p.getInventory().getViewers()).forEach(HumanEntity::closeInventory));
}
/**

View File

@ -223,10 +223,10 @@ public class PortalTeleportationListener implements Listener {
e.getEntity().setFallDistance(0);
}
// If we do not generate portals, teleporation should happen manually with safe spot builder.
// Otherwise, we could end up with situations when player is placed in mid air, if teleporation
// If we do not generate portals, teleportation should happen manually with safe spot builder.
// Otherwise, we could end up with situations when player is placed in mid air, if teleportation
// is done instantly.
// Our safe spot task is triggered in next tick, however, end teleporation happens in the same tick.
// Our safe spot task is triggered in next tick, however, end teleportation happens in the same tick.
// It is placed outside THE_END check, as technically it could happen with the nether portal too.
e.setCancelled(true);

View File

@ -34,7 +34,7 @@ public class BlockInteractionListener extends FlagListener {
*/
private final static Map<String, String> stringFlags;
static {
stringFlags = Map.<String, String>of("RESPAWN_ANCHOR", "PLACE_BLOCKS");
stringFlags = Map.of("RESPAWN_ANCHOR", "PLACE_BLOCKS");
}
/**

View File

@ -42,15 +42,12 @@ public class BucketListener extends FlagListener {
switch (e.getItemStack().getType()) {
case LAVA_BUCKET -> {
checkIsland(e, e.getPlayer(), e.getBlockClicked().getLocation(), Flags.COLLECT_LAVA);
return;
}
case WATER_BUCKET -> {
checkIsland(e, e.getPlayer(), e.getBlockClicked().getLocation(), Flags.COLLECT_WATER);
return;
}
case MILK_BUCKET -> {
checkIsland(e, e.getPlayer(), e.getBlockClicked().getLocation(), Flags.MILKING);
return;
}
default ->
// Check general bucket use

View File

@ -604,7 +604,7 @@ public class AddonsManager {
try {
addon.onDisable();
} catch (Exception e) {
plugin.logError("Error occured when disabling addon " + addon.getDescription().getName());
plugin.logError("Error occurred when disabling addon " + addon.getDescription().getName());
plugin.logError("Report this to the addon's author(s)");
addon.getDescription().getAuthors().forEach(plugin::logError);
plugin.logStacktrace(e);

View File

@ -77,7 +77,7 @@ public class BlueprintClipboardManager {
/**
* Load a file to clipboard
* @param fileName - filename in blueprints folder
* @throws IOException - if there's a load error with unziping or name
* @throws IOException - if there's a load error with unzipping or name
*/
public void load(String fileName) throws IOException {
clipboard = new BlueprintClipboard(loadBlueprint(fileName));

View File

@ -52,7 +52,7 @@ public class IslandDeletionManager implements Listener {
plugin.log("There are " + toBeDeleted.size() + " islands pending deletion.");
toBeDeleted.forEach(di -> {
if (di.getLocation() == null || di.getLocation().getWorld() == null) {
plugin.logError("Island queued for deletion refers to a non-existant game world. Skipping...");
plugin.logError("Island queued for deletion refers to a non-existent game world. Skipping...");
toBeRemoved.add(di);
} else {
plugin.log("Resuming deletion of island at " + di.getLocation().getWorld().getName() + " " + Util.xyz(di.getLocation().toVector()));

View File

@ -484,7 +484,7 @@ public class IslandsManager {
* Will update the value based on world settings or island owner permissions (if online).
* If the island is unowned, then this value will be 0.
* @param island - island
* @param rank {@link RanksManager.MEMBER_RANK}, {@link RanksManager.COOP_RANK}, or {@link RanksManager.TRUSTED_RANK}
* @param rank {@link RanksManager#MEMBER_RANK}, {@link RanksManager#COOP_RANK}, or {@link RanksManager#TRUSTED_RANK}
* @return max number of members. If negative, then this means unlimited.
* @since 1.16.0
*/
@ -521,7 +521,7 @@ public class IslandsManager {
/**
* Sets the island max member size.
* @param island - island
* @param rank {@link RanksManager.MEMBER_RANK}, {@link RanksManager.COOP_RANK}, or {@link RanksManager.TRUSTED_RANK}
* @param rank {@link RanksManager#MEMBER_RANK}, {@link RanksManager#COOP_RANK}, or {@link RanksManager#TRUSTED_RANK}
* @param maxMembers - max number of members. If negative, then this means unlimited. Null means the world
* default will be used.
* @since 1.16.0

View File

@ -23,7 +23,7 @@ import world.bentobox.bentobox.util.Util;
public class DefaultNewIslandLocationStrategy implements NewIslandLocationStrategy {
/**
* The amount times to tolerate island check returning blocks without kwnon
* The amount times to tolerate island check returning blocks without known
* island.
*/
protected static final Integer MAX_UNOWNED_ISLANDS = 20;

View File

@ -7,7 +7,6 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import org.bukkit.Location;
import org.bukkit.World;
@ -181,7 +180,7 @@ public class IslandCache {
return islandsByLocation.entrySet().stream()
.filter(entry -> overworld.equals(Util.getWorld(entry.getKey().getWorld()))) // shouldn't make NPEs
.map(Map.Entry::getValue).collect(Collectors.toUnmodifiableList());
.map(Map.Entry::getValue).toList();
}
/**

View File

@ -39,7 +39,7 @@ class IslandGrid {
if (firstLoaded.getOwner().equals(island.getOwner())) {
// Find out which one is the original
if (firstLoaded.getCreatedDate() > island.getCreatedDate()) {
plugin.logError("Same owner duplicate. Swaping based on creation date.");
plugin.logError("Same owner duplicate. Swapping based on creation date.");
// FirstLoaded is the newer
firstLoaded = new Island(island);
zEntry.put(island.getMinZ(), firstLoaded);

View File

@ -540,7 +540,7 @@ public class Util {
// Use matcher to find hex patterns in given text.
Matcher matcher = HEX_PATTERN.matcher(textToColor);
// Increase buffer size by 32 like it is in bungee cord api. Use buffer because it is sync.
StringBuffer buffer = new StringBuffer(textToColor.length() + 32);
StringBuilder buffer = new StringBuilder(textToColor.length() + 32);
while (matcher.find()) {
String group = matcher.group(1);

View File

@ -72,7 +72,7 @@ public class HeadGetter {
HeadCache cache = cachedHeads.get(panelItem.getPlayerHeadName());
// Get value from config. Multiply value to 60 000 as internally it uses miliseconds.
// Get value from config. Multiply value to 60 000 as internally it uses milliseconds.
// Config value stores minutes.
long cacheTimeout = BentoBox.getInstance().getSettings().getPlayerHeadCacheTime() * 60 * 1000;

View File

@ -380,7 +380,7 @@ public class SafeSpotTeleport {
/**
* Try to teleport the player
* @return CompletableFuture that will become true if successfull and false if not
* @return CompletableFuture that will become true if successful and false if not
* @since 1.14.0
*/
@Nullable

View File

@ -308,9 +308,9 @@ public class ServerCompatibility {
}
/**
* Returns whether the server runs on the specified softwares.
* Returns whether the server runs on the specified software.
* @param softwares the {@link ServerSoftware}s to check.
* @return {@code true} if the server runs on on of these softwares, {@code false} otherwise.
* @return {@code true} if the server runs on on of these software, {@code false} otherwise.
* @since 1.5.0
*/
public boolean isSoftware(@NonNull ServerSoftware... softwares) {

View File

@ -138,7 +138,7 @@ public class IslandDeletionManagerTest {
BentoBoxReadyEvent e = new BentoBoxReadyEvent();
idm.onBentoBoxReady(e);
verify(plugin).log("There are 1 islands pending deletion.");
verify(plugin).logError("Island queued for deletion refers to a non-existant game world. Skipping...");
verify(plugin).logError("Island queued for deletion refers to a non-existent game world. Skipping...");
}
/**