diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index 7e340a776a6..f8467b458e4 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 0064cb9181f..a823531acb0 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,3 @@ - diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index 63d286777ec..3e9f710485e 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -47,7 +47,7 @@ dependencies { implementation("org.terasology.gestalt:gestalt-module:7.1.0") // plugins we configure - implementation("com.github.spotbugs.snom:spotbugs-gradle-plugin:5.2.0") + implementation("com.github.spotbugs.snom:spotbugs-gradle-plugin:5.2.3") implementation("org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.3") api(kotlin("test")) diff --git a/build-logic/src/main/kotlin/terasology-metrics.gradle.kts b/build-logic/src/main/kotlin/terasology-metrics.gradle.kts index 5cf9a7e7449..0b3a3b28810 100644 --- a/build-logic/src/main/kotlin/terasology-metrics.gradle.kts +++ b/build-logic/src/main/kotlin/terasology-metrics.gradle.kts @@ -13,9 +13,17 @@ plugins { id("org.sonarqube") } +// give test dependencies access to compileOnly dependencies to emulate providedCompile +// only because of spotbugs-annotations in below dependencies. +configurations.testImplementation.get().extendsFrom(configurations.compileOnly.get()) + dependencies { - pmd("net.sourceforge.pmd:pmd-core:6.55.0") - pmd("net.sourceforge.pmd:pmd-java:6.55.0") + // spotbugs annotations to suppress warnings are not included via spotbugs plugin + // see bug: https://github.com/spotbugs/spotbugs-gradle-plugin/issues/1018 + compileOnly("com.github.spotbugs:spotbugs-annotations:4.8.1") + pmd("net.sourceforge.pmd:pmd-ant:7.0.0-rc4") + pmd("net.sourceforge.pmd:pmd-core:7.0.0-rc4") + pmd("net.sourceforge.pmd:pmd-java:7.0.0-rc4") testRuntimeOnly("ch.qos.logback:logback-classic:1.2.11") { because("runtime: to configure logging during tests with logback.xml") diff --git a/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/serializers/Serializer.java b/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/serializers/Serializer.java index e4a0586cc04..c9ffdd342a9 100644 --- a/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/serializers/Serializer.java +++ b/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/serializers/Serializer.java @@ -84,7 +84,7 @@ public Optional deserialize(TypeInfo type, InputStream inputStream) { D persistedData = reader.read(inputStream); return deserializeFromPersisted(persistedData, type); } catch (IOException e) { - logger.error("Cannot deserialize type [" + type + "]", e); + logger.error("Cannot deserialize type [{}]", type, e); } return Optional.empty(); } @@ -102,7 +102,7 @@ public Optional deserialize(TypeInfo type, byte[] bytes) { D persistedData = reader.read(bytes); return deserializeFromPersisted(persistedData, type); } catch (IOException e) { - logger.error("Cannot deserialize type [" + type + "]", e); + logger.error("Cannot deserialize type [{}]", type, e); } return Optional.empty(); } @@ -140,7 +140,7 @@ public void serialize(T object, TypeInfo type, OutputStream outputStream) try { writer.writeTo(persistedData.get(), outputStream); } catch (IOException e) { - logger.error("Cannot serialize [" + type + "]", e); + logger.error("Cannot serialize [{}]", type, e); } } else { logger.error("Cannot serialize [{}]", type); diff --git a/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/Serializer.java b/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/Serializer.java index 7cd7a19059b..1361e671f7f 100644 --- a/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/Serializer.java +++ b/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/Serializer.java @@ -18,8 +18,8 @@ public class Serializer { private static final Logger logger = LoggerFactory.getLogger(Serializer.class); - private ClassMetadata classMetadata; - private Map, TypeHandler> fieldHandlers; + private final ClassMetadata classMetadata; + private final Map, TypeHandler> fieldHandlers; public Serializer(ClassMetadata classMetadata, Map, TypeHandler> fieldHandlers) { this.fieldHandlers = fieldHandlers; diff --git a/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/coreTypes/EnumTypeHandler.java b/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/coreTypes/EnumTypeHandler.java index cd0bc4ba319..193a5d3393d 100644 --- a/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/coreTypes/EnumTypeHandler.java +++ b/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/coreTypes/EnumTypeHandler.java @@ -16,7 +16,7 @@ public class EnumTypeHandler extends TypeHandler { private static final Logger logger = LoggerFactory.getLogger(EnumTypeHandler.class); - private Class enumType; + private final Class enumType; private Map caseInsensitiveLookup = Maps.newHashMap(); public EnumTypeHandler(Class enumType) { diff --git a/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/coreTypes/factories/ObjectFieldMapTypeHandlerFactory.java b/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/coreTypes/factories/ObjectFieldMapTypeHandlerFactory.java index 7da6f3f4851..488f6404997 100644 --- a/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/coreTypes/factories/ObjectFieldMapTypeHandlerFactory.java +++ b/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/coreTypes/factories/ObjectFieldMapTypeHandlerFactory.java @@ -3,8 +3,6 @@ package org.terasology.persistence.typeHandling.coreTypes.factories; import com.google.common.collect.Maps; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.terasology.persistence.typeHandling.TypeHandler; import org.terasology.persistence.typeHandling.TypeHandlerContext; import org.terasology.persistence.typeHandling.TypeHandlerFactory; @@ -23,7 +21,6 @@ import java.util.Optional; public class ObjectFieldMapTypeHandlerFactory implements TypeHandlerFactory { - private static final Logger LOGGER = LoggerFactory.getLogger(ObjectFieldMapTypeHandlerFactory.class); private ConstructorLibrary constructorLibrary; diff --git a/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/inMemory/PersistedBytes.java b/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/inMemory/PersistedBytes.java index 3585432edff..057beede8a6 100644 --- a/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/inMemory/PersistedBytes.java +++ b/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/inMemory/PersistedBytes.java @@ -5,6 +5,8 @@ import java.nio.ByteBuffer; +// TODO, see https://github.com/MovingBlocks/Terasology/issues/5176 for reasoning. +@SuppressWarnings({"PMD.ArrayIsStoredDirectly", "PMD.MethodReturnsInternalArray"}) public class PersistedBytes extends AbstractPersistedData { private final byte[] bytes; diff --git a/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/inMemory/arrays/PersistedBooleanArray.java b/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/inMemory/arrays/PersistedBooleanArray.java index 214308cbfc8..13658863a06 100644 --- a/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/inMemory/arrays/PersistedBooleanArray.java +++ b/subsystems/TypeHandlerLibrary/src/main/java/org/terasology/persistence/typeHandling/inMemory/arrays/PersistedBooleanArray.java @@ -9,6 +9,8 @@ import java.util.Arrays; import java.util.Iterator; +// TODO, see https://github.com/MovingBlocks/Terasology/issues/5176 for reasoning. +@SuppressWarnings({"PMD.ArrayIsStoredDirectly", "PMD.MethodReturnsInternalArray"}) public class PersistedBooleanArray extends AbstractPersistedArray { private final boolean[] booleans; diff --git a/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/FutureTypeHandlerTest.java b/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/FutureTypeHandlerTest.java index bd485d52815..5e89fcd7ec0 100644 --- a/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/FutureTypeHandlerTest.java +++ b/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/FutureTypeHandlerTest.java @@ -27,30 +27,6 @@ public class FutureTypeHandlerTest { private final TypeHandlerLibrary typeHandlerLibrary = Mockito.spy(new TypeHandlerLibrary(reflections)); - private static final class RecursiveType { - final T data; - final List> children; - - @SafeVarargs - private RecursiveType(T data, RecursiveType... children) { - this.data = data; - this.children = Lists.newArrayList(children); - } - } - - private class ResultCaptor implements Answer { - private T result = null; - public T getResult() { - return result; - } - - @Override - public T answer(InvocationOnMock invocationOnMock) throws Throwable { - result = (T) invocationOnMock.callRealMethod(); - return result; - } - } - @Test public void testRecursiveType() { ResultCaptor>>> resultCaptor = new ResultCaptor<>(); @@ -77,4 +53,32 @@ public void testRecursiveType() { assertEquals(typeHandler, future.typeHandler); } + + private static final class RecursiveType { + final T data; + final List> children; + + @SafeVarargs + private RecursiveType(T data, RecursiveType... children) { + this.data = data; + this.children = Lists.newArrayList(children); + } + } + + @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( + value = "SIC_INNER_SHOULD_BE_STATIC", + justification = "Test code is not performance-relevant, flagged inner ResultCaptor class is a mock with dynamic behavior" + + " and cannot be static.") + private class ResultCaptor implements Answer { + private T result = null; + public T getResult() { + return result; + } + + @Override + public T answer(InvocationOnMock invocationOnMock) throws Throwable { + result = (T) invocationOnMock.callRealMethod(); + return result; + } + } } diff --git a/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/InMemorySerializerTest.java b/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/InMemorySerializerTest.java index 8d77751f98b..8da2f82f4b1 100644 --- a/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/InMemorySerializerTest.java +++ b/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/InMemorySerializerTest.java @@ -37,9 +37,8 @@ import java.util.function.Function; import java.util.stream.Stream; - class InMemorySerializerTest { - private InMemoryPersistedDataSerializer serializer = new InMemoryPersistedDataSerializer(); + private final InMemoryPersistedDataSerializer serializer = new InMemoryPersistedDataSerializer(); public static Stream types() { return Stream.of( @@ -123,30 +122,6 @@ void serializeStrings() { Assertions.assertThrows(ClassCastException.class, data::getAsDouble); } - //TODO remove it - public void template(PersistedData data) { - Assertions.assertFalse(data.isString()); - Assertions.assertFalse(data.isArray()); - Assertions.assertFalse(data.isNull()); - Assertions.assertFalse(data.isNumber()); - Assertions.assertFalse(data.isBoolean()); - Assertions.assertFalse(data.isBytes()); - Assertions.assertFalse(data.isValueMap()); - - Assertions.assertThrows(IllegalStateException.class, data::getAsValueMap); - Assertions.assertThrows(IllegalStateException.class, data::getAsArray); - - Assertions.assertThrows(DeserializationException.class, data::getAsByteBuffer); - Assertions.assertThrows(DeserializationException.class, data::getAsBytes); - - Assertions.assertThrows(ClassCastException.class, data::getAsString); - Assertions.assertThrows(ClassCastException.class, data::getAsBoolean); - Assertions.assertThrows(ClassCastException.class, data::getAsInteger); - Assertions.assertThrows(ClassCastException.class, data::getAsLong); - Assertions.assertThrows(ClassCastException.class, data::getAsFloat); - Assertions.assertThrows(ClassCastException.class, data::getAsDouble); - } - @Test void serializeOneAsStrings() { PersistedData data = serializer.serialize(new String[]{"foo"}); @@ -306,7 +281,7 @@ void serializeBytes() { Assertions.assertEquals(PersistedBytes.class, data.getClass()); Assertions.assertTrue(data.isBytes()); - Assertions.assertEquals(value, data.getAsBytes()); + Assertions.assertArrayEquals(value, data.getAsBytes()); Assertions.assertEquals(ByteBuffer.wrap(value), data.getAsByteBuffer()); Assertions.assertFalse(data.isString()); @@ -335,7 +310,7 @@ void serializeByteBuffer() { Assertions.assertEquals(PersistedBytes.class, data.getClass()); Assertions.assertTrue(data.isBytes()); - Assertions.assertEquals(value, data.getAsBytes()); + Assertions.assertArrayEquals(value, data.getAsBytes()); Assertions.assertEquals(ByteBuffer.wrap(value), data.getAsByteBuffer()); Assertions.assertFalse(data.isString()); @@ -469,7 +444,7 @@ private void checkValueArray(PersistedData data, PersistedData entry, Set Assertions.assertEquals(typeGetter.getGetter().apply(entry), typeGetter.getGetter().apply(data)) diff --git a/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/TypeHandlerLibraryTest.java b/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/TypeHandlerLibraryTest.java index 6d027341def..09659522ebe 100644 --- a/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/TypeHandlerLibraryTest.java +++ b/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/TypeHandlerLibraryTest.java @@ -22,19 +22,15 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class TypeHandlerLibraryTest { - private static Reflections reflections; private static TypeHandlerLibrary typeHandlerLibrary; @BeforeAll public static void setup() { - reflections = new Reflections(TypeHandlerLibraryTest.class.getClassLoader()); + Reflections reflections = new Reflections(TypeHandlerLibraryTest.class.getClassLoader()); typeHandlerLibrary = new TypeHandlerLibrary(reflections); TypeHandlerLibrary.populateBuiltInHandlers(typeHandlerLibrary); } - @MappedContainer - private static class AMappedContainer { } - @Test public void testMappedContainerHandler() { TypeHandler handler = typeHandlerLibrary.getTypeHandler(AMappedContainer.class).get(); @@ -93,4 +89,7 @@ void testGetBaseTypeHandler() { } private enum AnEnum { } + + @MappedContainer + private static class AMappedContainer { } } diff --git a/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/coreTypes/factories/BytesTypeHandlerTest.java b/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/coreTypes/factories/BytesTypeHandlerTest.java index f0d9690bbb7..dff71f2ae62 100644 --- a/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/coreTypes/factories/BytesTypeHandlerTest.java +++ b/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/coreTypes/factories/BytesTypeHandlerTest.java @@ -39,10 +39,10 @@ void byteArraySerializeDeserialize() { byte[] expectedObj = new byte[]{(byte) 0xFF}; PersistedBytes data = serialize(expectedObj, new ByteArrayTypeHandler()); - Assertions.assertEquals(expectedObj, data.getAsBytes()); + Assertions.assertArrayEquals(expectedObj, data.getAsBytes()); byte[] obj = deserialize(data, new ByteArrayTypeHandler()); - Assertions.assertEquals(expectedObj, obj); + Assertions.assertArrayEquals(expectedObj, obj); } private R serialize(T obj, TypeHandler typeHandler) { diff --git a/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/coreTypes/factories/ObjectFieldMapTypeHandlerFactoryTest.java b/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/coreTypes/factories/ObjectFieldMapTypeHandlerFactoryTest.java index c6e73e3bd7a..738dbfb45b5 100644 --- a/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/coreTypes/factories/ObjectFieldMapTypeHandlerFactoryTest.java +++ b/subsystems/TypeHandlerLibrary/src/test/java/org/terasology/persistence/typeHandling/coreTypes/factories/ObjectFieldMapTypeHandlerFactoryTest.java @@ -112,4 +112,14 @@ private static class MultiTypeClass { private T t; private U u; } + + @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( + value = "UUF_UNUSED_FIELD", + justification = "Direct member access is not expected. TypeHandler factory dynamically loads type handlers on type handler" + + " creation based on member types of input class TypeInfo. ") + @SuppressWarnings("PMD.UnusedPrivateField") + private static class SomeClass { + private T t; + private List list; + } }