Repository: victools/jsonschema-generator
Pull request #330 (2023-03-20 21:50:17)

feat: Support additional Draft 2019-09 keywords
- [x] Add `dependentRequired`, `dependentSchemas`, `unevaluatedProperties`, `unevaluatedItems`, `prefixItems` as recognized items to the `SchemaKeyword` enum and consider them in the final schema clean-up logic (they were introduced in Draft 2019-09 already)
- [x] Introduce configuration support for the `dependentRequired` keyword
- [x] Add unit tests for extended schema clean-up logic: `dependentRequired`
- [x] Add unit tests for configurable `dependentRequired`
- [x] Mention new configuration option in documentation


Patch:
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/MemberScope.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/MemberScope.java
index 802ff01..c6d728a 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/MemberScope.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/MemberScope.java
@@ -39,7 +39,6 @@ public abstract class MemberScope<M extends ResolvedMember<T>, T extends Member>
     private final String overriddenName;
     private final ResolvedTypeWithMembers declaringTypeMembers;
     private Integer fakeContainerItemIndex;
-    private final TypeContext context;
     private final LazyValue<String> schemaPropertyName = new LazyValue<>(this::doGetSchemaPropertyName);
 
     /**
@@ -60,7 +59,6 @@ public abstract class MemberScope<M extends ResolvedMember<T>, T extends Member>
         this.overriddenName = overriddenName;
         this.declaringTypeMembers = declaringTypeMembers;
         this.fakeContainerItemIndex = fakeContainerItemIndex;
-        this.context = context;
     }
 
     /**
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/Option.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/Option.java
index e446509..197afaf 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/Option.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/Option.java
@@ -324,7 +324,7 @@ public enum Option {
      * @param disabledModuleProvider type of the module realising this setting/option if it is disabled
      * @param overriddenOptions other options being ignored if this one is enabled
      */
-    private Option(Supplier<Module> enabledModuleProvider, Supplier<Module> disabledModuleProvider, Option... overriddenOptions) {
+    Option(Supplier<Module> enabledModuleProvider, Supplier<Module> disabledModuleProvider, Option... overriddenOptions) {
         this.enabledModuleProvider = enabledModuleProvider;
         this.disabledModuleProvider = disabledModuleProvider;
         if (overriddenOptions == null || overriddenOptions.length == 0) {
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfig.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfig.java
index c4f101d..c518f61 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfig.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfig.java
@@ -472,6 +472,23 @@ public interface SchemaGeneratorConfig extends StatefulConfig {
      */
     Object resolveDefaultForType(TypeScope scope);
 
+    /**
+     * Determine the "dependentRequired" list of other properties' names, for which a value is required if the given field is present.
+     *
+     * @param field object's field/property to collect dependent property names for
+     * @return "dependentRequired" list in a JSON Schema associated with the targeted field (may be empty)
+     */
+    List<String> resolveDependentRequires(FieldScope field);
+
+    /**
+     * Determine the "dependentRequired" list of other properties' names, for which a value is required if the given method
+     * (or more likely: the field derived from this method) is present.
+     *
+     * @param method method to collect dependent property names for
+     * @return "dependentRequired" list in a JSON Schema associated with the targeted method (may be empty)
+     */
+    List<String> resolveDependentRequires(MethodScope method);
+
     /**
      * Determine the "enum"/"const" of an object's field/property.
      *
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigPart.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigPart.java
index 7e5ac0a..a52123a 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigPart.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigPart.java
@@ -52,6 +52,7 @@ public class SchemaGeneratorConfigPart<M extends MemberScope<?, ?>> extends Sche
     private final List<Predicate<M>> readOnlyChecks = new ArrayList<>();
     private final List<Predicate<M>> writeOnlyChecks = new ArrayList<>();
     private final List<ConfigFunction<M, Boolean>> nullableChecks = new ArrayList<>();
+    private final List<ConfigFunction<M, List<String>>> dependentRequiresResolvers = new ArrayList<>();
 
     /*
      * Customising options for the names of properties in a schema with "type": "object".
@@ -222,6 +223,34 @@ public class SchemaGeneratorConfigPart<M extends MemberScope<?, ?>> extends Sche
         return result.isEmpty() ? null : result.stream().anyMatch(value -> value);
     }
 
+    /**
+     * Setter for resolver, that collects the names of other properties that are required depending on the targeted one.
+     * <br>
+     * Beware that the output of all configured resolvers are combined, i.e., not just considering the first that returns a value.
+     *
+     * @param resolver how to determine which other properties should have a required value if the given one is present.
+     * @return this config part (for chaining)
+     */
+    public SchemaGeneratorConfigPart<M> withDependentRequiresResolver(ConfigFunction<M, List<String>> resolver) {
+        this.dependentRequiresResolvers.add(resolver);
+        return this;
+    }
+
+    /**
+     * Determine the names of other properties that are required to have a value, if the given member is present.
+     *
+     * @param member member to check
+     * @return list of other properties' names (may be empty)
+     */
+    public List<String> resolveDependentRequires(M member) {
+        return this.dependentRequiresResolvers.stream()
+                .map(resolver -> resolver.apply(member))
+                .filter(Objects::nonNull)
+                .flatMap(List::stream)
+                .distinct()
+                .collect(Collectors.toList());
+    }
+
     /**
      * Setter for target type resolver, expecting the respective member as input. NOTE: there is an alternative method allowing for multiple
      * type overrides at once: {@link #withTargetTypeOverridesResolver(ConfigFunction)}
@@ -393,7 +422,7 @@ public class SchemaGeneratorConfigPart<M extends MemberScope<?, ?>> extends Sche
         super.resetAfterSchemaGenerationFinished();
 
         Stream.of(this.customDefinitionProviders, this.instanceAttributeOverrides, this.nullableChecks,
-                this.targetTypeOverridesResolvers, this.propertyNameOverrideResolvers
+                this.dependentRequiresResolvers, this.targetTypeOverridesResolvers, this.propertyNameOverrideResolvers
         ).flatMap(List::stream).forEach(StatefulConfig::resetAfterSchemaGenerationFinished);
     }
 }
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaKeyword.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaKeyword.java
index 18a49fc..d52706f 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaKeyword.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaKeyword.java
@@ -55,8 +55,30 @@ public enum SchemaKeyword {
     TAG_TYPE_NUMBER("number", Type.VALUE),
 
     TAG_PROPERTIES("properties", Type.TAG),
+    /**
+     * Beware that this keyword was only introduced in {@link SchemaVersion#DRAFT_2019_09}.
+     */
+    TAG_UNEVALUATED_PROPERTIES("unevaluatedProperties", Type.TAG),
     TAG_ITEMS("items", Type.TAG),
+    /**
+     * Beware that this keyword was only introduced in {@link SchemaVersion#DRAFT_2019_09}.
+     */
+    TAG_PREFIX_ITEMS("prefixItems", Type.TAG),
+    /**
+     * Beware that this keyword was only introduced in {@link SchemaVersion#DRAFT_2019_09}.
+     */
+    TAG_UNEVALUATED_ITEMS("unevaluatedItems", Type.TAG),
     TAG_REQUIRED("required", Type.TAG),
+    /**
+     * Prior to {@link SchemaVersion#DRAFT_2019_09}, this had the same name as {@link #TAG_DEPENDENT_SCHEMAS}.
+     */
+    TAG_DEPENDENT_REQUIRED(version -> version == SchemaVersion.DRAFT_6 || version == SchemaVersion.DRAFT_7
+            ? "dependencies" : "dependentRequired", Type.TAG),
+    /**
+     * Prior to {@link SchemaVersion#DRAFT_2019_09}, this had the same name as {@link #TAG_DEPENDENT_REQUIRED}.
+     */
+    TAG_DEPENDENT_SCHEMAS(version -> version == SchemaVersion.DRAFT_6 || version == SchemaVersion.DRAFT_7
+            ? "dependencies" : "dependentSchemas", Type.TAG),
     TAG_ADDITIONAL_PROPERTIES("additionalProperties", Type.TAG),
     TAG_PATTERN_PROPERTIES("patternProperties", Type.TAG),
     TAG_PROPERTIES_MIN("minProperties", Type.TAG),
@@ -118,7 +140,7 @@ public enum SchemaKeyword {
      * @param fixedValue single value applying regardless of schema version
      * @param keywordType what kind of keyword this represents
      */
-    private SchemaKeyword(String fixedValue, SchemaKeyword.Type keywordType) {
+    SchemaKeyword(String fixedValue, SchemaKeyword.Type keywordType) {
         this(_version -> fixedValue, keywordType);
     }
 
@@ -128,7 +150,7 @@ public enum SchemaKeyword {
      * @param valueProvider dynamic value provider that may return different values base on specific JSON Schema versions
      * @param keywordType what kind of keyword this represents
      */
-    private SchemaKeyword(Function<SchemaVersion, String> valueProvider, SchemaKeyword.Type keywordType) {
+    SchemaKeyword(Function<SchemaVersion, String> valueProvider, SchemaKeyword.Type keywordType) {
         this.valueProvider = valueProvider;
         this.type = keywordType;
     }
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaVersion.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaVersion.java
index 7c10df2..e310b16 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaVersion.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaVersion.java
@@ -32,7 +32,7 @@ public enum SchemaVersion {
      *
      * @param schemaIdentifier value for the {@code $schema} tag
      */
-    private SchemaVersion(String schemaIdentifier) {
+    SchemaVersion(String schemaIdentifier) {
         this.identifier = schemaIdentifier;
     }
 
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SubtypeResolver.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SubtypeResolver.java
index 6d94647..17e71a3 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SubtypeResolver.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SubtypeResolver.java
@@ -41,7 +41,7 @@ public interface SubtypeResolver extends StatefulConfig {
      * @param declaredType declared type (i.e. without type parameter information)
      * @param context generation context (including a reference to the {@code TypeContext} for deriving a {@link ResolvedType} from a {@link Class})
      * @return list of subtypes to represent as separate schemas (may return {@code null})
-     * @see SchemaGeneratorConfigPart#withTargetTypeOverrideResolver(ConfigFunction)
+     * @see SchemaGeneratorConfigPart#withTargetTypeOverridesResolver(ConfigFunction)
      */
     List<ResolvedType> findSubtypes(ResolvedType declaredType, SchemaGenerationContext context);
 }
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/AttributeCollector.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/AttributeCollector.java
index c62648f..a2e2f71 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/AttributeCollector.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/AttributeCollector.java
@@ -470,7 +470,7 @@ public class AttributeCollector {
      */
     public AttributeCollector setReadOnly(ObjectNode node, boolean readOnly, SchemaGenerationContext generationContext) {
         if (readOnly) {
-            node.put(generationContext.getKeyword(SchemaKeyword.TAG_READ_ONLY), readOnly);
+            node.put(generationContext.getKeyword(SchemaKeyword.TAG_READ_ONLY), true);
         }
         return this;
     }
@@ -485,7 +485,7 @@ public class AttributeCollector {
      */
     public AttributeCollector setWriteOnly(ObjectNode node, boolean writeOnly, SchemaGenerationContext generationContext) {
         if (writeOnly) {
-            node.put(generationContext.getKeyword(SchemaKeyword.TAG_WRITE_ONLY), writeOnly);
+            node.put(generationContext.getKeyword(SchemaKeyword.TAG_WRITE_ONLY), true);
         }
         return this;
     }
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/PropertySortUtils.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/PropertySortUtils.java
index 13c0104..db477c4 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/PropertySortUtils.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/PropertySortUtils.java
@@ -36,7 +36,7 @@ public class PropertySortUtils {
      * @see MemberScope#getSchemaPropertyName()
      */
     public static final Comparator<MemberScope<?, ?>> SORT_PROPERTIES_BY_NAME_ALPHABETICALLY
-            = (first, second) -> first.getSchemaPropertyName().compareTo(second.getSchemaPropertyName());
+            = Comparator.comparing(MemberScope::getSchemaPropertyName);
 
     /**
      * {@link Comparator} sorting properties into the following groups and within each group alphabetically by their name.
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaCleanUpUtils.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaCleanUpUtils.java
index 007b445..f5f46d3 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaCleanUpUtils.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaCleanUpUtils.java
@@ -27,6 +27,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -62,7 +63,7 @@ public class SchemaCleanUpUtils {
     public void reduceAllOfNodes(List<ObjectNode> jsonSchemas) {
         String allOfTagName = this.config.getKeyword(SchemaKeyword.TAG_ALLOF);
         Map<String, SchemaKeyword> reverseKeywordMap = SchemaKeyword.getTagStream()
-                .collect(Collectors.toMap(this.config::getKeyword, keyword -> keyword));
+                .collect(Collectors.toMap(this.config::getKeyword, keyword -> keyword, (k1, k2) -> k1));
         this.finaliseSchemaParts(jsonSchemas, nodeToCheck -> this.mergeAllOfPartsIfPossible(nodeToCheck, allOfTagName, reverseKeywordMap));
     }
 
@@ -83,7 +84,6 @@ public class SchemaCleanUpUtils {
      * {@link SchemaKeyword#TAG_ITEMS}.
      *
      * @return names of eligible tags as per the designated JSON Schema version
-     * @see #discardUnnecessaryAllOfWrappers(ObjectNode)
      */
     private Set<String> getTagNamesContainingSchema() {
         SchemaVersion schemaVersion = this.config.getSchemaVersion();
@@ -97,7 +97,6 @@ public class SchemaCleanUpUtils {
      * {@link SchemaKeyword#TAG_ONEOF}.
      *
      * @return names of eligible tags as per the designated JSON Schema version
-     * @see #discardUnnecessaryAllOfWrappers(ObjectNode)
      */
     private Set<String> getTagNamesContainingSchemaArray() {
         SchemaVersion schemaVersion = this.config.getSchemaVersion();
@@ -111,7 +110,6 @@ public class SchemaCleanUpUtils {
      * {@link SchemaKeyword#TAG_PROPERTIES}.
      *
      * @return names of eligible tags as per the designated JSON Schema version
-     * @see #discardUnnecessaryAllOfWrappers(ObjectNode)
      */
     private Set<String> getTagNamesContainingSchemaObject() {
         SchemaVersion schemaVersion = this.config.getSchemaVersion();
@@ -148,11 +146,11 @@ public class SchemaCleanUpUtils {
                 tagsWithSchemas.stream().map(nodeToCheck::get).forEach(addNodeToCheck);
                 tagsWithSchemaArrays.stream()
                         .map(nodeToCheck::get)
-                        .filter(possibleArrayNode -> possibleArrayNode instanceof ArrayNode)
+                        .filter(ArrayNode.class::isInstance)
                         .forEach(arrayNode -> arrayNode.forEach(addNodeToCheck));
                 tagsWithSchemaObjects.stream()
                         .map(nodeToCheck::get)
-                        .filter(possibleObjectNode -> possibleObjectNode instanceof ObjectNode)
+                        .filter(ObjectNode.class::isInstance)
                         .forEach(objectNode -> objectNode.forEach(addNodeToCheck));
             }
         } while (!nextNodesToCheck.isEmpty());
@@ -203,9 +201,14 @@ public class SchemaCleanUpUtils {
         case TAG_REQUIRED:
             return this.mergeArrays(valuesToMerge);
         case TAG_PROPERTIES:
+        case TAG_DEPENDENT_SCHEMAS:
             return this.mergeObjectProperties(valuesToMerge);
+        case TAG_DEPENDENT_REQUIRED:
+            return this.mergeDependentRequiredNode(valuesToMerge);
         case TAG_ITEMS:
+        case TAG_UNEVALUATED_ITEMS:
         case TAG_ADDITIONAL_PROPERTIES:
+        case TAG_UNEVALUATED_PROPERTIES:
             return this.mergeSchemas(null, valuesToMerge, reverseKeywordMap);
         case TAG_TYPE:
             return this.returnOverlapOfStringsOrStringArrays(valuesToMerge);
@@ -250,10 +253,7 @@ public class SchemaCleanUpUtils {
                 Map.Entry<String, JsonNode> singleField = it.next();
                 if (!mergedObjectNode.has(singleField.getKey())) {
                     mergedObjectNode.set(singleField.getKey(), singleField.getValue());
-                } else if (mergedObjectNode.get(singleField.getKey()).equals(singleField.getValue())) {
-                    // preserve equal existing node
-                    continue;
-                } else {
+                } else if (!mergedObjectNode.get(singleField.getKey()).equals(singleField.getValue())) {
                     // cannot consolidate two occurrences of the same property; abort merge (in the future: may want to be smarter here)
                     return null;
                 }
@@ -262,6 +262,41 @@ public class SchemaCleanUpUtils {
         return () -> mergedObjectNode;
     }
 
+    private Supplier<JsonNode> mergeDependentRequiredNode(List<JsonNode> dependentRequiredNodesToMerge) {
+        if (!dependentRequiredNodesToMerge.stream().allMatch(JsonNode::isObject)) {
+            // at least one value is not an object as expected, abort merge
+            return null;
+        }
+        Map<String, Set<String>> mergedDependentRequiredNames = new LinkedHashMap<>();
+        for (JsonNode singleDependentRequired : dependentRequiredNodesToMerge) {
+            Iterator<Map.Entry<String, JsonNode>> it = singleDependentRequired.fields();
+            while (it.hasNext()) {
+                Map.Entry<String, JsonNode> singleLeadingField = it.next();
+                if (!singleLeadingField.getValue().isArray()) {
+                    // cannot consolidate when anything but an array of other property names is being provided
+                    return null;
+                } else {
+                    Set<String> propertyNames = mergedDependentRequiredNames.computeIfAbsent(singleLeadingField.getKey(),
+                            (name) -> new LinkedHashSet<>());
+                    Iterator<JsonNode> propertyNameIt = singleLeadingField.getValue().elements();
+                    while (propertyNameIt.hasNext()) {
+                        JsonNode propertyName = propertyNameIt.next();
+                        if (!propertyName.isTextual()) {
+                            // cannot consolidate when array contains anything but plain property names
+                            return null;
+                        }
+                        propertyNames.add(propertyName.asText());
+                    }
+                }
+            }
+        }
+        // merging is possible, now build corresponding object node
+        ObjectNode mergedDependentRequiredNode = this.config.createObjectNode();
+        mergedDependentRequiredNames.forEach((leadName, dependentNames) -> dependentNames
+                .forEach(mergedDependentRequiredNode.withArray(leadName)::add));
+        return () -> mergedDependentRequiredNode;
+    }
+
     /**
      * Determine whether a given list of sub-schema nodes can be merged into a single schema node. If yes, providing a supplier that performs the
      * actual consolidation once called.
@@ -276,13 +311,13 @@ public class SchemaCleanUpUtils {
             return null;
         }
         List<ObjectNode> parts = nodes.stream()
-                .filter(part -> part instanceof ObjectNode)
-                .map(part -> (ObjectNode) part)
+                .filter(ObjectNode.class::isInstance)
+                .map(ObjectNode.class::cast)
                 .collect(Collectors.toList());
 
         // collect all defined attributes from the separate parts and check whether there are incompatible differences
         Map<String, List<JsonNode>> fieldsFromAllParts = parts.stream()
-                .flatMap(part -> StreamSupport.stream(((Iterable<Map.Entry<String, JsonNode>>) () -> part.fields()).spliterator(), false))
+                .flatMap(part -> StreamSupport.stream(((Iterable<Map.Entry<String, JsonNode>>) part::fields).spliterator(), false))
                 .collect(Collectors.groupingBy(Map.Entry::getKey, LinkedHashMap::new, Collectors.mapping(Map.Entry::getValue, Collectors.toList())));
         if ((this.config.getSchemaVersion() == SchemaVersion.DRAFT_6 || this.config.getSchemaVersion() == SchemaVersion.DRAFT_7)
                 && fieldsFromAllParts.containsKey(this.config.getKeyword(SchemaKeyword.TAG_REF))
@@ -387,14 +422,14 @@ public class SchemaCleanUpUtils {
     }
 
     private Supplier<JsonNode> returnMinimumNumericValue(List<JsonNode> nodes) {
-        if (nodes.stream().allMatch(node -> node.isNumber())) {
+        if (nodes.stream().allMatch(JsonNode::isNumber)) {
             return () -> nodes.stream().reduce((a, b) -> a.asDouble() < b.asDouble() ? a : b).get();
         }
         return null;
     }
 
     private Supplier<JsonNode> returnMaximumNumericValue(List<JsonNode> nodes) {
-        if (nodes.stream().allMatch(node -> node.isNumber())) {
+        if (nodes.stream().allMatch(JsonNode::isNumber)) {
             return () -> nodes.stream().reduce((a, b) -> a.asDouble() < b.asDouble() ? b : a).get();
         }
         return null;
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGenerationContextImpl.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGenerationContextImpl.java
index 20ad50b..f2a6908 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGenerationContextImpl.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGenerationContextImpl.java
@@ -453,19 +453,26 @@ public class SchemaGenerationContextImpl implements SchemaGenerationContext {
             List<MemberScope<?, ?>> sortedProperties = targetProperties.values().stream()
                     .sorted(this.generatorConfig::sortProperties)
                     .collect(Collectors.toList());
+            Map<String, List<String>> dependentRequires = new LinkedHashMap<>();
             for (MemberScope<?, ?> property : sortedProperties) {
                 JsonNode subSchema;
+                List<String> dependentRequiredForProperty;
                 if (property instanceof FieldScope) {
                     subSchema = this.populateFieldSchema((FieldScope) property);
+                    dependentRequiredForProperty = this.generatorConfig.resolveDependentRequires((FieldScope) property);
                 } else if (property instanceof MethodScope) {
                     subSchema = this.populateMethodSchema((MethodScope) property);
+                    dependentRequiredForProperty = this.generatorConfig.resolveDependentRequires((MethodScope) property);
                 } else {
                     throw new IllegalStateException("Unsupported member scope of type " + property.getClass());
                 }
-                propertiesNode.set(property.getSchemaPropertyName(), subSchema);
+                String propertyName = property.getSchemaPropertyName();
+                propertiesNode.set(propertyName, subSchema);
+                if (dependentRequiredForProperty != null && !dependentRequiredForProperty.isEmpty()) {
+                    dependentRequires.put(propertyName, dependentRequiredForProperty);
+                }
             }
             definition.set(this.getKeyword(SchemaKeyword.TAG_PROPERTIES), propertiesNode);
-
             if (!requiredProperties.isEmpty()) {
                 ArrayNode requiredNode = this.generatorConfig.createArrayNode();
                 // list required properties in the same order as the property
@@ -475,6 +482,12 @@ public class SchemaGenerationContextImpl implements SchemaGenerationContext {
                         .forEach(requiredNode::add);
                 definition.set(this.getKeyword(SchemaKeyword.TAG_REQUIRED), requiredNode);
             }
+            if (!dependentRequires.isEmpty()) {
+                ObjectNode dpendentRequiredNode = this.generatorConfig.createObjectNode();
+                dependentRequires.forEach((leadName, dependentNames) -> dependentNames
+                        .forEach(dpendentRequiredNode.withArray(leadName)::add));
+                definition.set(this.getKeyword(SchemaKeyword.TAG_DEPENDENT_REQUIRED), dpendentRequiredNode);
+            }
         }
     }
 
@@ -728,7 +741,7 @@ public class SchemaGenerationContextImpl implements SchemaGenerationContext {
      * @param forceInlineDefinition whether to generate an inline definition without registering it in this context
      * @param collectedAttributes separately collected attribute for the field/method in their respective declaring type
      * @param ignoredDefinitionProvider first custom definition provider to ignore
-     * @see #populateField(FieldScope, Map, Set)
+     * @see #populateFieldSchema(FieldScope)
      * @see #collectMethod(MethodScope, Map, Set)
      */
     private <M extends MemberScope<?, ?>> void populateMemberSchema(M scope, ObjectNode targetNode, boolean isNullable, boolean forceInlineDefinition,
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGeneratorConfigImpl.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGeneratorConfigImpl.java
index 8f09c78..be0d7d5 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGeneratorConfigImpl.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGeneratorConfigImpl.java
@@ -227,7 +227,7 @@ public class SchemaGeneratorConfigImpl implements SchemaGeneratorConfig {
      * @param context generation context allowing to let the standard generation take over nested parts of the custom definition
      * @param ignoredDefinitionProvider custom definition provider to ignore
      * @return non-standard JSON schema definition (may be null)
-     * @see #getCustomDefinition(ResolvedType, SchemaGenerationContext, CustomDefinitionProviderV3)
+     * @see #getCustomDefinition(ResolvedType, SchemaGenerationContext, CustomDefinitionProviderV2)
      */
     private <M extends MemberScope<?, ?>> CustomPropertyDefinition getCustomDefinition(SchemaGeneratorConfigPart<M> configPart, M scope,
             SchemaGenerationContext context, CustomPropertyDefinitionProvider<? extends M> ignoredDefinitionProvider) {
@@ -411,6 +411,16 @@ public class SchemaGeneratorConfigImpl implements SchemaGeneratorConfig {
         return this.typesInGeneralConfigPart.resolveDefault(scope);
     }
 
+    @Override
+    public List<String> resolveDependentRequires(FieldScope field) {
+        return this.fieldConfigPart.resolveDependentRequires(field);
+    }
+
+    @Override
+    public List<String> resolveDependentRequires(MethodScope method) {
+        return this.methodConfigPart.resolveDependentRequires(method);
+    }
+
     @Override
     public Collection<?> resolveEnum(FieldScope field) {
         return this.fieldConfigPart.resolveEnum(field);
diff --git a/jsonschema-maven-plugin/src/main/java/com/github/victools/jsonschema/plugin/maven/SchemaGeneratorMojo.java b/jsonschema-maven-plugin/src/main/java/com/github/victools/jsonschema/plugin/maven/SchemaGeneratorMojo.java
index a0f557f..897cd30 100644
--- a/jsonschema-maven-plugin/src/main/java/com/github/victools/jsonschema/plugin/maven/SchemaGeneratorMojo.java
+++ b/jsonschema-maven-plugin/src/main/java/com/github/victools/jsonschema/plugin/maven/SchemaGeneratorMojo.java
@@ -494,7 +494,7 @@ public class SchemaGeneratorMojo extends AbstractMojo {
             // fix the classpath such that the classloader can get classes from any possible dependency
             // this does not affect filtering, as the classgraph library uses its own classloader and allows for caching
             List<URL> urls = ClasspathType.WITH_ALL_DEPENDENCIES.getUrls(this.project);
-            this.classLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]),
+            this.classLoader = new URLClassLoader(urls.toArray(new URL[0]),
                 Thread.currentThread().getContextClassLoader());
         }
         return this.classLoader;
diff --git a/jsonschema-maven-plugin/src/main/java/com/github/victools/jsonschema/plugin/maven/StandardOptionPreset.java b/jsonschema-maven-plugin/src/main/java/com/github/victools/jsonschema/plugin/maven/StandardOptionPreset.java
index 725d78d..2f4b7b8 100644
--- a/jsonschema-maven-plugin/src/main/java/com/github/victools/jsonschema/plugin/maven/StandardOptionPreset.java
+++ b/jsonschema-maven-plugin/src/main/java/com/github/victools/jsonschema/plugin/maven/StandardOptionPreset.java
@@ -29,7 +29,7 @@ public enum StandardOptionPreset {
 
     private final OptionPreset preset;
 
-    private StandardOptionPreset(OptionPreset preset) {
+    StandardOptionPreset(OptionPreset preset) {
         this.preset = preset;
     }
 
diff --git a/jsonschema-module-jackson/src/main/java/com/github/victools/jsonschema/module/jackson/JsonIdentityReferenceDefinitionProvider.java b/jsonschema-module-jackson/src/main/java/com/github/victools/jsonschema/module/jackson/JsonIdentityReferenceDefinitionProvider.java
index d328812..b380cf6 100644
--- a/jsonschema-module-jackson/src/main/java/com/github/victools/jsonschema/module/jackson/JsonIdentityReferenceDefinitionProvider.java
+++ b/jsonschema-module-jackson/src/main/java/com/github/victools/jsonschema/module/jackson/JsonIdentityReferenceDefinitionProvider.java
@@ -18,6 +18,7 @@ package com.github.victools.jsonschema.module.jackson;
 
 import com.fasterxml.classmate.ResolvedType;
 import com.fasterxml.classmate.members.ResolvedField;
+import com.fasterxml.classmate.members.ResolvedMember;
 import com.fasterxml.jackson.annotation.JsonIdentityInfo;
 import com.fasterxml.jackson.annotation.JsonIdentityReference;
 import com.fasterxml.jackson.annotation.ObjectIdGenerator;
@@ -120,7 +121,7 @@ public class JsonIdentityReferenceDefinitionProvider implements CustomDefinition
             ResolvedField[] eligibleFields = typeContext.resolveWithMembers(typeWithIdentityInfoAnnotation).getMemberFields();
             Optional<ResolvedType> identityTypeFromProperty = Stream.of(eligibleFields)
                     .filter(field -> field.getName().equals(idPropertyName))
-                    .map(field -> field.getType())
+                    .map(ResolvedMember::getType)
                     .findFirst();
             if (identityTypeFromProperty.isPresent()) {
                 return identityTypeFromProperty;
diff --git a/jsonschema-module-jackson/src/main/java/com/github/victools/jsonschema/module/jackson/JsonSubTypesResolver.java b/jsonschema-module-jackson/src/main/java/com/github/victools/jsonschema/module/jackson/JsonSubTypesResolver.java
index 5d12197..cff9c6b 100644
--- a/jsonschema-module-jackson/src/main/java/com/github/victools/jsonschema/module/jackson/JsonSubTypesResolver.java
+++ b/jsonschema-module-jackson/src/main/java/com/github/victools/jsonschema/module/jackson/JsonSubTypesResolver.java
@@ -258,7 +258,7 @@ public class JsonSubTypesResolver implements SubtypeResolver, CustomDefinitionPr
         return Stream.of(subTypesAnnotation.value())
                 .filter(subTypeAnnotation -> erasedTargetType.equals(subTypeAnnotation.value()))
                 .findFirst()
-                .map(subTypeAnnotation -> subTypeAnnotation.name())
+                .map(JsonSubTypes.Type::name)
                 .filter(name -> !name.isEmpty());
     }
 
diff --git a/jsonschema-module-swagger-2/src/main/java/com/github/victools/jsonschema/module/swagger2/Swagger2SubtypeResolver.java b/jsonschema-module-swagger-2/src/main/java/com/github/victools/jsonschema/module/swagger2/Swagger2SubtypeResolver.java
index 2e51587..cd117da 100644
--- a/jsonschema-module-swagger-2/src/main/java/com/github/victools/jsonschema/module/swagger2/Swagger2SubtypeResolver.java
+++ b/jsonschema-module-swagger-2/src/main/java/com/github/victools/jsonschema/module/swagger2/Swagger2SubtypeResolver.java
@@ -43,7 +43,7 @@ public class Swagger2SubtypeResolver implements SubtypeResolver {
                     .collect(Collectors.toList());
         }
         return Stream.of(annotation.anyOf())
-                .map(erasedType -> typeContext.resolve(erasedType))
+                .map(typeContext::resolve)
                 .collect(Collectors.toList());
     }
 }
diff --git a/slate-docs/source/includes/_main-generator.md b/slate-docs/source/includes/_main-generator.md
index 45b78a2..3cbca95 100644
--- a/slate-docs/source/includes/_main-generator.md
+++ b/slate-docs/source/includes/_main-generator.md
@@ -246,8 +246,8 @@ configBuilder.without(
       <td colspan="2"><code>Option.MAP_VALUES_AS_ADDITIONAL_PROPERTIES</code></td>
     </tr>
     <tr>
-      <td>Setting the <code>additionalProperties</code> attribute in each <code>Map<K, V></code> to a schema representing the declared value type <code>V</code>.</td>
-      <td>Omitting the <code>additionalProperties</code> attribute in <code>Map<K, V></code> schemas by default (thereby allowing additional properties of any type) unless some configuration specifically says something else.</td>
+      <td>Setting the <code>additionalProperties</code> attribute in each <code>Map&lt;K, V&gt;</code> to a schema representing the declared value type <code>V</code>.</td>
+      <td>Omitting the <code>additionalProperties</code> attribute in <code>Map&lt;K, V&gt;</code> schemas by default (thereby allowing additional properties of any type) unless some configuration specifically says something else.</td>
     </tr>
     <tr>
       <td rowspan="2" style="text-align: right">26</td>
@@ -562,6 +562,24 @@ configBuilder.forMethods()
 
 `withRequiredCheck()` is expecting the indication to be returned whether a given `FieldScope`/`MethodScope` should be included in the `"required"` attribute – if any check returns `true`, the field/method will be deemed `"required"`.
 
+## `"dependentRequired"` Keyword
+```java
+configBuilder.forFields()
+    .withDependentRequiresResolver(field -> Optional
+        .ofNullable(field.getAnnotationConsideringFieldAndGetter(IfPresentAlsoRequire.class)
+        .map(IfPresentAlsoRequire::value)
+        .map(Arrays::asList)
+        .orElse(null));
+configBuilder.forMethods()
+    .withDependentRequiresResolver(method -> Optional.ofNullable(method.findGetterField())
+        .map(FieldScope::getSchemaPropertyName)
+        .map(Collections::singletonList)
+        .orElse(null));
+```
+
+`withDependentRequiresResolver()` is expecting the names of other properties to be returned, which should be deemed "required", if the property represented by the given field/method is present.
+The results of all registered resolvers are being combined.
+
 ## `"readOnly"` Keyword
 ```java
 configBuilder.forFields()


Test patch:
diff --git a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/FieldScopeTest.java b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/FieldScopeTest.java
index a154a2c..d3e1be9 100644
--- a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/FieldScopeTest.java
+++ b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/FieldScopeTest.java
@@ -124,6 +124,6 @@ public class FieldScopeTest extends AbstractTypeAwareTest {
 
     @Retention(RetentionPolicy.RUNTIME)
     @Target({ElementType.FIELD, ElementType.METHOD})
-    private static @interface TestAnnotation {
+    private @interface TestAnnotation {
     }
 }
diff --git a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/MethodScopeTest.java b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/MethodScopeTest.java
index 4efe374..51de57d 100644
--- a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/MethodScopeTest.java
+++ b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/MethodScopeTest.java
@@ -29,7 +29,7 @@ import org.junit.jupiter.params.provider.CsvSource;
 import org.junit.jupiter.params.provider.MethodSource;
 
 /**
- * Test for the {@link MethodSCope} class.
+ * Test for the {@link MethodScope} class.
  */
 public class MethodScopeTest extends AbstractTypeAwareTest {
 
@@ -153,6 +153,6 @@ public class MethodScopeTest extends AbstractTypeAwareTest {
 
     @Retention(RetentionPolicy.RUNTIME)
     @Target({ElementType.FIELD, ElementType.METHOD})
-    private static @interface TestAnnotation {
+    private @interface TestAnnotation {
     }
 }
diff --git a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorAllOfCleanUpTest.java b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorAllOfCleanUpTest.java
index b810487..96e11da 100644
--- a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorAllOfCleanUpTest.java
+++ b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorAllOfCleanUpTest.java
@@ -60,11 +60,18 @@ public class SchemaGeneratorAllOfCleanUpTest {
         // in Drafts 6/7, alongside $ref all other attributes are being ignored and should therefore not be merged
         EnumSet<SchemaVersion> versionsWithSpecialRefHandling = EnumSet.of(SchemaVersion.DRAFT_6, SchemaVersion.DRAFT_7);
         String refInAllOfPart = "{ \"type\": \"object\", \"allOf\": [{ \"$ref\": \"#\" }, { \"title\": \"value\" }] }";
-        versionsWithSpecialRefHandling.stream()
-                .forEach(schemaVersion -> testCases.add(Arguments.of(schemaVersion, refInAllOfPart, refInAllOfPart)));
-        EnumSet.complementOf(versionsWithSpecialRefHandling).stream()
-                .forEach(schemaVersion ->
-        testCases.add(Arguments.of(schemaVersion, refInAllOfPart, "{ \"type\": \"object\", \"$ref\": \"#\", \"title\": \"value\" }")));
+        versionsWithSpecialRefHandling.forEach(schemaVersion -> testCases.add(
+                Arguments.of(schemaVersion, refInAllOfPart, refInAllOfPart)));
+        EnumSet.complementOf(versionsWithSpecialRefHandling).forEach(schemaVersion -> testCases.add(
+                Arguments.of(schemaVersion, refInAllOfPart, "{ \"type\": \"object\", \"$ref\": \"#\", \"title\": \"value\" }")));
+
+        // the keyword for "dependentRequired" changed, but not the handling for it
+        for (SchemaVersion schemaVersion : EnumSet.allOf(SchemaVersion.class)) {
+            String tag = SchemaKeyword.TAG_DEPENDENT_REQUIRED.forVersion(schemaVersion);
+            String drInput = "{ \"" + tag + "\": {\"a\": [\"b\"]}, \"allOf\": [{}, { \"" + tag + "\": { \"a\": [\"c\"], \"b\": [\"a\", \"c\"] } }] }";
+            String drCleanOutput = "{ \"" + tag + "\": { \"a\": [\"b\", \"c\"], \"b\": [\"a\", \"c\"] } }";
+            testCases.add(Arguments.of(schemaVersion, drInput, drCleanOutput));
+        }
         return testCases.stream();
     }
 
diff --git a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorComplexTypesTest.java b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorComplexTypesTest.java
index 1ca63b7..7423ccf 100644
--- a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorComplexTypesTest.java
+++ b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorComplexTypesTest.java
@@ -51,7 +51,7 @@ public class SchemaGeneratorComplexTypesTest {
                 .withDefaultResolver(scope -> scope.getType().isInstanceOf(Number.class) ? 1 : null)
                 .withDescriptionResolver(scope -> descriptionPrefix + scope.getSimpleTypeDescription())
                 .withEnumResolver(scope -> scope.getType().isInstanceOf(Number.class) ? Arrays.asList(1, 2, 3, 4, 5) : null)
-                .withEnumResolver(scope -> scope.getType().isInstanceOf(String.class) ? Arrays.asList("constant string value") : null)
+                .withEnumResolver(scope -> scope.getType().isInstanceOf(String.class) ? Collections.singletonList("constant string value") : null)
                 .withAdditionalPropertiesResolver(SchemaGeneratorComplexTypesTest::resolveAdditionalProperties)
                 .withPatternPropertiesResolver(SchemaGeneratorComplexTypesTest::resolvePatternProperties)
                 .withNumberExclusiveMaximumResolver(scope -> scope.getType().isInstanceOf(Number.class) ? BigDecimal.TEN.add(BigDecimal.ONE) : null)
@@ -63,7 +63,7 @@ public class SchemaGeneratorComplexTypesTest {
                 .withStringMaxLengthResolver(scope -> scope.getType().isInstanceOf(String.class) ? 256 : null)
                 .withStringMinLengthResolver(scope -> scope.getType().isInstanceOf(String.class) ? 1 : null)
                 .withStringPatternResolver(scope -> scope.getType().isInstanceOf(String.class) ? "^.{1,256}$" : null)
-                .withTitleResolver(scope -> scope.getSimpleTypeDescription());
+                .withTitleResolver(TypeScope::getSimpleTypeDescription);
     }
 
     private static Type resolveAdditionalProperties(TypeScope scope) {
@@ -93,7 +93,7 @@ public class SchemaGeneratorComplexTypesTest {
         configPart
                 .withNullableCheck(member -> !member.getName().startsWith("nested"))
                 .withRequiredCheck(member -> member.getName().startsWith("nested"))
-                .withReadOnlyCheck(member -> member.isFinal())
+                .withReadOnlyCheck(MemberScope::isFinal)
                 .withWriteOnlyCheck(member -> member.getType() != null && TestClass4.class.isAssignableFrom(member.getType().getErasedType()));
     }
 
@@ -149,7 +149,7 @@ public class SchemaGeneratorComplexTypesTest {
         // ensure that the generated definition keys are valid URIs without any characters requiring encoding
         JsonNode definitions = result.get(SchemaKeyword.TAG_DEFINITIONS.forVersion(schemaVersion));
         if (definitions instanceof ObjectNode) {
-            Iterator<String> definitionKeys = ((ObjectNode) definitions).fieldNames();
+            Iterator<String> definitionKeys = definitions.fieldNames();
             while (definitionKeys.hasNext()) {
                 String key = definitionKeys.next();
                 Assertions.assertEquals(key, new URI(key).toASCIIString());
@@ -241,7 +241,7 @@ public class SchemaGeneratorComplexTypesTest {
         public TestClass2<TestClassCircular> class2OfCircular;
     }
 
-    private static enum TestEnum {
+    private enum TestEnum {
         VALUE1, VALUE2, VALUE3;
 
         @Override
diff --git a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigPartTest.java b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigPartTest.java
index 876a85f..7a24c14 100644
--- a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigPartTest.java
+++ b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigPartTest.java
@@ -108,6 +108,30 @@ public class SchemaGeneratorConfigPartTest {
         Assertions.assertFalse(this.instance.isNullable(this.field3));
     }
 
+    @Test
+    public void testDependentRequires() {
+        Assertions.assertEquals(Collections.emptyList(), this.instance.resolveDependentRequires(this.field1));
+
+        ConfigFunction<FieldScope, List<String>> resolver1 = member -> member == this.field1 ? Collections.singletonList("field2") : null;
+        Assertions.assertSame(this.instance, this.instance.withDependentRequiresResolver(resolver1));
+        Assertions.assertEquals(Collections.singletonList("field2"), this.instance.resolveDependentRequires(this.field1));
+        Assertions.assertEquals(Collections.emptyList(), this.instance.resolveDependentRequires(this.field2));
+        Assertions.assertEquals(Collections.emptyList(), this.instance.resolveDependentRequires(this.field3));
+
+        ConfigFunction<FieldScope, List<String>> resolver2 = member -> member == this.field1 ? Collections.singletonList("field3") : null;
+        Assertions.assertSame(this.instance, this.instance.withDependentRequiresResolver(resolver2));
+        Assertions.assertEquals(Arrays.asList("field2", "field3"), this.instance.resolveDependentRequires(this.field1));
+        Assertions.assertEquals(Collections.emptyList(), this.instance.resolveDependentRequires(this.field2));
+        Assertions.assertEquals(Collections.emptyList(), this.instance.resolveDependentRequires(this.field3));
+
+        ConfigFunction<FieldScope, List<String>> resolver3 = member -> member == this.field3
+                ? Collections.emptyList() : Arrays.asList("field3", "field4");
+        Assertions.assertSame(this.instance, this.instance.withDependentRequiresResolver(resolver3));
+        Assertions.assertEquals(Arrays.asList("field2", "field3", "field4"), this.instance.resolveDependentRequires(this.field1));
+        Assertions.assertEquals(Arrays.asList("field3", "field4"), this.instance.resolveDependentRequires(this.field2));
+        Assertions.assertEquals(Collections.emptyList(), this.instance.resolveDependentRequires(this.field3));
+    }
+
     @Test
     @SuppressWarnings("deprecation")
     public void testTargetTypeOverride() {
@@ -177,7 +201,7 @@ public class SchemaGeneratorConfigPartTest {
 
     @Test
     public void testEnum() {
-        this.testFirstDefinedValueConfig(Arrays.asList("val1", "val2"), Arrays.asList("val3"),
+        this.testFirstDefinedValueConfig(Arrays.asList("val1", "val2"), Collections.singletonList("val3"),
                 this.instance::withEnumResolver, this.instance::resolveEnum);
     }
 
diff --git a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/TestUtils.java b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/TestUtils.java
index 98c6535..fc54adf 100644
--- a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/TestUtils.java
+++ b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/TestUtils.java
@@ -66,7 +66,6 @@ public abstract class TestUtils {
                 stringBuilder.append(scanner.nextLine()).append('\n');
             }
         }
-        String fileAsString = stringBuilder.toString();
-        return fileAsString;
+        return stringBuilder.toString();
     }
 }
diff --git a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/AttributeCollectorTest.java b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/AttributeCollectorTest.java
index bb0c95d..ca80ab2 100644
--- a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/AttributeCollectorTest.java
+++ b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/AttributeCollectorTest.java
@@ -81,7 +81,7 @@ public class AttributeCollectorTest {
     @ParameterizedTest
     @EnumSource(SchemaVersion.class)
     public void testSetEnum_singleConstValue(SchemaVersion schemaVersion) {
-        this.collector.setEnum(this.definitionNode, Arrays.asList("A"), this.generateContext(schemaVersion));
+        this.collector.setEnum(this.definitionNode, Collections.singletonList("A"), this.generateContext(schemaVersion));
         JsonNode constNode = this.definitionNode.get(SchemaKeyword.TAG_CONST.forVersion(schemaVersion));
         Assertions.assertNotNull(constNode);
         Assertions.assertTrue(constNode.isTextual());
@@ -91,7 +91,7 @@ public class AttributeCollectorTest {
     @ParameterizedTest
     @EnumSource(SchemaVersion.class)
     public void testSetEnum_singleEnumValue(SchemaVersion schemaVersion) {
-        this.collector.setEnum(this.definitionNode, Arrays.asList("A"), this.generateContext(schemaVersion, Option.ENUM_KEYWORD_FOR_SINGLE_VALUES));
+        this.collector.setEnum(this.definitionNode, Collections.singletonList("A"), this.generateContext(schemaVersion, Option.ENUM_KEYWORD_FOR_SINGLE_VALUES));
         JsonNode enumNode = this.definitionNode.get(SchemaKeyword.TAG_ENUM.forVersion(schemaVersion));
         Assertions.assertNotNull(enumNode);
         Assertions.assertTrue(enumNode.isArray());
diff --git a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/SchemaGenerationContextImplTest.java b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/SchemaGenerationContextImplTest.java
index fb2b27b..9a4282c 100644
--- a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/SchemaGenerationContextImplTest.java
+++ b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/SchemaGenerationContextImplTest.java
@@ -59,6 +59,8 @@ public class SchemaGenerationContextImplTest extends AbstractTypeAwareTest {
         Mockito.when(config.resolveTitle(Mockito.any(FieldScope.class))).thenReturn("Field Title");
         Mockito.when(config.resolveTitle(Mockito.any(MethodScope.class))).thenReturn("Method Title");
         Mockito.when(config.resolveDescriptionForType(Mockito.any())).thenReturn("Type Description");
+        Mockito.when(config.resolveDependentRequires(Mockito.any(FieldScope.class))).thenReturn(Collections.singletonList("isBooleanField()"));
+        Mockito.when(config.resolveDependentRequires(Mockito.any(MethodScope.class))).thenReturn(Collections.singletonList("booleanField"));
         Mockito.when(config.resolveStringMinLength(Mockito.any(FieldScope.class))).thenReturn(null);
         Mockito.when(config.resolveStringMaxLength(Mockito.any(FieldScope.class))).thenReturn(null);
         Mockito.when(config.resolveArrayMinItems(Mockito.any(FieldScope.class))).thenReturn(null);
@@ -281,6 +283,18 @@ public class SchemaGenerationContextImplTest extends AbstractTypeAwareTest {
         Assertions.assertEquals("{\"$comment\":\"custom property\"}", result.toString());
     }
 
+    @Test
+    public void testCreateStandardDefinition() {
+        ResolvedType type = this.contextImpl.getTypeContext().resolve(TestClass.class);
+        ObjectNode result = this.contextImpl.createStandardDefinition(type, null);
+        Assertions.assertEquals("{\"type\":\"object\",\"properties\":{"
+                        + "\"booleanField\":{\"allOf\":[{},{\"title\":\"Field Title\"}]},"
+                        + "\"isBooleanField()\":{\"allOf\":[{},{\"title\":\"Method Title\"}]}},"
+                        + "\"dependentRequired\":{\"booleanField\":[\"isBooleanField()\"],\"isBooleanField()\":[\"booleanField\"]}," +
+                        "\"description\":\"Type Description\"}",
+                result.toString());
+    }
+
     private static class TestClass {
 
         public boolean booleanField;
diff --git a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/SchemaGeneratorConfigImplTest.java b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/SchemaGeneratorConfigImplTest.java
index 84e18b1..6a6e477 100644
--- a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/SchemaGeneratorConfigImplTest.java
+++ b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/SchemaGeneratorConfigImplTest.java
@@ -162,7 +162,7 @@ public class SchemaGeneratorConfigImplTest extends AbstractTypeAwareTest {
 
     @ParameterizedTest
     @MethodSource("parametersForTestIsNullable")
-    public void testIsNullableField(Boolean configResult, boolean optionEnabled, boolean expectedResult) throws Exception {
+    public void testIsNullableField(Boolean configResult, boolean optionEnabled, boolean expectedResult) {
         FieldScope field = this.getTestClassField("field");
         Mockito.when(this.fieldConfigPart.isNullable(field)).thenReturn(configResult);
         if (optionEnabled) {
@@ -174,7 +174,7 @@ public class SchemaGeneratorConfigImplTest extends AbstractTypeAwareTest {
 
     @ParameterizedTest
     @MethodSource("parametersForTestIsNullable")
-    public void testIsNullableMethod(Boolean configResult, boolean optionEnabled, boolean expectedResult) throws Exception {
+    public void testIsNullableMethod(Boolean configResult, boolean optionEnabled, boolean expectedResult) {
         MethodScope method = this.getTestClassMethod("getField");
         Mockito.when(this.methodConfigPart.isNullable(method)).thenReturn(configResult);
         if (optionEnabled) {
@@ -186,7 +186,7 @@ public class SchemaGeneratorConfigImplTest extends AbstractTypeAwareTest {
 
     @ParameterizedTest
     @ValueSource(booleans = {true, false})
-    public void testIsRequiredField(boolean configuredAndExpectedResult) throws Exception {
+    public void testIsRequiredField(boolean configuredAndExpectedResult) {
         FieldScope field = this.getTestClassField("field");
         Mockito.when(this.fieldConfigPart.isRequired(field)).thenReturn(configuredAndExpectedResult);
         boolean result = this.instance.isRequired(field);
@@ -195,13 +195,31 @@ public class SchemaGeneratorConfigImplTest extends AbstractTypeAwareTest {
 
     @ParameterizedTest
     @ValueSource(booleans = {true, false})
-    public void testIsRequiredMethod(boolean configuredAndExpectedResult) throws Exception {
+    public void testIsRequiredMethod(boolean configuredAndExpectedResult) {
         MethodScope method = this.getTestClassMethod("getField");
         Mockito.when(this.methodConfigPart.isRequired(method)).thenReturn(configuredAndExpectedResult);
         boolean result = this.instance.isRequired(method);
         Assertions.assertEquals(configuredAndExpectedResult, result);
     }
 
+    @Test
+    public void testResolveDependentRequiresField() {
+        List<String> configuredAndExceptedResult = Collections.singletonList("otherField");
+        FieldScope field = this.getTestClassField("field");
+        Mockito.when(this.fieldConfigPart.resolveDependentRequires(field)).thenReturn(configuredAndExceptedResult);
+        List<String> result = this.instance.resolveDependentRequires(field);
+        Assertions.assertEquals(configuredAndExceptedResult, result);
+    }
+
+    @Test
+    public void testResolveDependentRequiresMethod() {
+        List<String> configuredAndExceptedResult = Collections.singletonList("otherMethod");
+        MethodScope method = this.getTestClassMethod("getField");
+        Mockito.when(this.methodConfigPart.resolveDependentRequires(method)).thenReturn(configuredAndExceptedResult);
+        List<String> result = this.instance.resolveDependentRequires(method);
+        Assertions.assertEquals(configuredAndExceptedResult, result);
+    }
+
     @Test
     public void testGetTypeAttributeOverrides() {
         TypeAttributeOverrideV2 typeOverride = (typeNode, type, c) -> typeNode.put("$comment", type.getSimpleTypeDescription());
diff --git a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/AdditionalPropertiesModuleTest.java b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/AdditionalPropertiesModuleTest.java
index 9017780..0241072 100644
--- a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/AdditionalPropertiesModuleTest.java
+++ b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/AdditionalPropertiesModuleTest.java
@@ -166,7 +166,7 @@ public class AdditionalPropertiesModuleTest extends AbstractTypeAwareTest {
     @Documented
     private @interface ParamInfo {
 
-        public abstract String value();
+        String value();
     }
 
     private static class A {
diff --git a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/ConstantValueModuleTest.java b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/ConstantValueModuleTest.java
index d424c44..498b175 100644
--- a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/ConstantValueModuleTest.java
+++ b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/ConstantValueModuleTest.java
@@ -55,7 +55,6 @@ public class ConstantValueModuleTest extends AbstractTypeAwareTest {
     }
 
     @Test
-    @SuppressWarnings("unchecked")
     public void testApplyToConfigBuilder() {
         this.instance.applyToConfigBuilder(this.builder);
 
diff --git a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/EnumModuleTest.java b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/EnumModuleTest.java
index b41f469..6e74991 100644
--- a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/EnumModuleTest.java
+++ b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/EnumModuleTest.java
@@ -153,7 +153,7 @@ public class EnumModuleTest extends AbstractTypeAwareTest {
 
         JsonNode enumNode = node.get(SchemaKeyword.TAG_ENUM.forVersion(schemaVersion));
         Assertions.assertEquals(JsonNodeType.ARRAY, enumNode.getNodeType());
-        Assertions.assertEquals(3, ((ArrayNode) enumNode).size());
+        Assertions.assertEquals(3, enumNode.size());
         Assertions.assertEquals(JsonNodeType.STRING, enumNode.get(0).getNodeType());
         Assertions.assertEquals(value1, enumNode.get(0).textValue());
         Assertions.assertEquals(JsonNodeType.STRING, enumNode.get(1).getNodeType());
@@ -162,7 +162,7 @@ public class EnumModuleTest extends AbstractTypeAwareTest {
         Assertions.assertEquals(value3, enumNode.get(2).textValue());
     }
 
-    private static enum TestEnum {
+    private enum TestEnum {
         VALUE1, VALUE2, VALUE3;
 
         @Override
diff --git a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/FieldExclusionModuleTest.java b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/FieldExclusionModuleTest.java
index fdf86bb..dd5e92c 100644
--- a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/FieldExclusionModuleTest.java
+++ b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/FieldExclusionModuleTest.java
@@ -52,7 +52,6 @@ public class FieldExclusionModuleTest extends AbstractTypeAwareTest {
     }
 
     @Test
-    @SuppressWarnings("unchecked")
     public void testApplyToConfigBuilder() {
         Predicate<FieldScope> ignoreCheck = field -> true;
         FieldExclusionModule module = new FieldExclusionModule(ignoreCheck);
diff --git a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/MethodExclusionModuleTest.java b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/MethodExclusionModuleTest.java
index bfb8db2..1225e77 100644
--- a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/MethodExclusionModuleTest.java
+++ b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/impl/module/MethodExclusionModuleTest.java
@@ -52,7 +52,6 @@ public class MethodExclusionModuleTest extends AbstractTypeAwareTest {
     }
 
     @Test
-    @SuppressWarnings("unchecked")
     public void testApplyToConfigBuilder() {
         Predicate<MethodScope> ignoreCheck = method -> true;
         MethodExclusionModule module = new MethodExclusionModule(ignoreCheck);
diff --git a/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/CustomEnumDefinitionProviderTest.java b/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/CustomEnumDefinitionProviderTest.java
index 25cffc4..56c1f31 100644
--- a/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/CustomEnumDefinitionProviderTest.java
+++ b/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/CustomEnumDefinitionProviderTest.java
@@ -31,6 +31,7 @@ import com.github.victools.jsonschema.generator.SchemaVersion;
 import com.github.victools.jsonschema.generator.TypeContext;
 import com.github.victools.jsonschema.generator.impl.TypeContextFactory;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.stream.Stream;
 import org.junit.jupiter.api.Assertions;
@@ -63,8 +64,8 @@ public class CustomEnumDefinitionProviderTest {
 
     static Stream<Arguments> parametersForTestProvideCustomSchemaDefinition() {
         return Stream.of(
-            Arguments.of(EnumWithInactiveJsonValueAndJsonProperty.class, true, true, Arrays.asList("entry")),
-            Arguments.of(EnumWithInactiveJsonValueAndJsonProperty.class, false, true, Arrays.asList("entry")),
+            Arguments.of(EnumWithInactiveJsonValueAndJsonProperty.class, true, true, Collections.singletonList("entry")),
+            Arguments.of(EnumWithInactiveJsonValueAndJsonProperty.class, false, true, Collections.singletonList("entry")),
             Arguments.of(EnumWithJsonValueAndJsonProperty.class, true, false, Arrays.asList("json-value-ENTRY1", "json-value-ENTRY2")),
             Arguments.of(EnumWithJsonValueAndJsonProperty.class, true, true, Arrays.asList("json-value-ENTRY1", "json-value-ENTRY2")),
             Arguments.of(EnumWithJsonValueAndJsonProperty.class, false, true, Arrays.asList("entry1", "ENTRY2"))
@@ -186,7 +187,7 @@ public class CustomEnumDefinitionProviderTest {
         }
     }
 
-    private static enum EmptyEnumWithJsonValue {
+    private enum EmptyEnumWithJsonValue {
         ;
 
         @JsonValue
@@ -195,7 +196,7 @@ public class CustomEnumDefinitionProviderTest {
         }
     }
 
-    private static enum EnumWithInvalidJsonValue {
+    private enum EnumWithInvalidJsonValue {
         ENTRY;
 
         @JsonValue
@@ -204,7 +205,7 @@ public class CustomEnumDefinitionProviderTest {
         }
     }
 
-    private static enum EnumWithInactiveJsonValueAndJsonProperty {
+    private enum EnumWithInactiveJsonValueAndJsonProperty {
         @JsonProperty("entry") ENTRY;
 
         @JsonValue(false)
@@ -213,7 +214,7 @@ public class CustomEnumDefinitionProviderTest {
         }
     }
 
-    private static enum EnumWithTwoJsonValuesAndIncompleteJsonProperty {
+    private enum EnumWithTwoJsonValuesAndIncompleteJsonProperty {
         ENTRY1,
         @JsonProperty("only-entry-2") ENTRY2;
 
@@ -228,7 +229,7 @@ public class CustomEnumDefinitionProviderTest {
         }
     }
 
-    private static enum EnumWithJsonValueAndJsonProperty {
+    private enum EnumWithJsonValueAndJsonProperty {
         @JsonProperty("entry1") ENTRY1,
         @JsonProperty ENTRY2;
 
diff --git a/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/IntegrationTest.java b/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/IntegrationTest.java
index bbd05f1..4a81341 100644
--- a/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/IntegrationTest.java
+++ b/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/IntegrationTest.java
@@ -43,11 +43,6 @@ import org.skyscreamer.jsonassert.JSONCompareMode;
  */
 public class IntegrationTest {
 
-    /**
-     * Test
-     *
-     * @throws Exception
-     */
     @Test
     public void testIntegration() throws Exception {
         JacksonModule module = new JacksonModule(JacksonOption.FLATTENED_ENUMS_FROM_JSONVALUE, JacksonOption.FLATTENED_ENUMS_FROM_JSONPROPERTY,
@@ -74,8 +69,7 @@ public class IntegrationTest {
                 stringBuilder.append(scanner.nextLine()).append('\n');
             }
         }
-        String fileAsString = stringBuilder.toString();
-        return fileAsString;
+        return stringBuilder.toString();
 
     }
 
@@ -108,11 +102,11 @@ public class IntegrationTest {
         }
     }
 
-    static enum TestEnum {
-        A, B, C;
+    enum TestEnum {
+        A, B, C
     }
 
-    static enum TestEnumWithJsonValueAnnotation {
+    enum TestEnumWithJsonValueAnnotation {
         ENTRY1, ENTRY2, ENTRY3;
 
         @JsonValue
@@ -121,16 +115,16 @@ public class IntegrationTest {
         }
     }
 
-    static enum TestEnumWithJsonPropertyAnnotations {
+    enum TestEnumWithJsonPropertyAnnotations {
         @JsonProperty("x_property") X,
-        @JsonProperty Y;
+        @JsonProperty Y
     }
 
     @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
     static class TestTypeWithObjectId {
         IdType id;
 
-        class IdType {
+        static class IdType {
             public String version;
             public long value;
         }
diff --git a/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/JsonIdentityReferenceDefinitionProviderTest.java b/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/JsonIdentityReferenceDefinitionProviderTest.java
index 490007e..62d0061 100644
--- a/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/JsonIdentityReferenceDefinitionProviderTest.java
+++ b/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/JsonIdentityReferenceDefinitionProviderTest.java
@@ -148,7 +148,7 @@ public class JsonIdentityReferenceDefinitionProviderTest extends AbstractTypeAwa
     private static class TestTypeReferencedByObjectId {
         private IdType id;
 
-        private class IdType {
+        private static class IdType {
         }
     }
 
@@ -156,7 +156,7 @@ public class JsonIdentityReferenceDefinitionProviderTest extends AbstractTypeAwa
     private static class TestTypeWithObjectIdRequiringReferenceAnnotation {
         private IdType id;
 
-        private class IdType {
+        private static class IdType {
         }
     }
 }
diff --git a/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/SubtypeResolutionFromInterfaceIntegrationTest.java b/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/SubtypeResolutionFromInterfaceIntegrationTest.java
index d15c714..8762115 100644
--- a/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/SubtypeResolutionFromInterfaceIntegrationTest.java
+++ b/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/SubtypeResolutionFromInterfaceIntegrationTest.java
@@ -82,8 +82,7 @@ public class SubtypeResolutionFromInterfaceIntegrationTest {
                 stringBuilder.append(scanner.nextLine()).append('\n');
             }
         }
-        String fileAsString = stringBuilder.toString();
-        return fileAsString;
+        return stringBuilder.toString();
 
     }
 
diff --git a/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/SubtypeResolutionIntegrationTest.java b/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/SubtypeResolutionIntegrationTest.java
index 4c7044e..e04bb72 100644
--- a/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/SubtypeResolutionIntegrationTest.java
+++ b/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/SubtypeResolutionIntegrationTest.java
@@ -82,8 +82,7 @@ public class SubtypeResolutionIntegrationTest {
                 stringBuilder.append(scanner.nextLine()).append('\n');
             }
         }
-        String fileAsString = stringBuilder.toString();
-        return fileAsString;
+        return stringBuilder.toString();
     }
 
     private static class TestClassForSubtypeResolution {
diff --git a/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/SubtypeResolutionSimpleIntegrationTest.java b/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/SubtypeResolutionSimpleIntegrationTest.java
index f749704..4b79698 100644
--- a/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/SubtypeResolutionSimpleIntegrationTest.java
+++ b/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/SubtypeResolutionSimpleIntegrationTest.java
@@ -79,8 +79,7 @@ public class SubtypeResolutionSimpleIntegrationTest {
                 stringBuilder.append(scanner.nextLine()).append('\n');
             }
         }
-        String fileAsString = stringBuilder.toString();
-        return fileAsString;
+        return stringBuilder.toString();
     }
 
     private static class TestClassForSubtypeResolution {
diff --git a/jsonschema-module-jakarta-validation/src/test/java/com/github/victools/jsonschema/module/jakarta/validation/IntegrationTest.java b/jsonschema-module-jakarta-validation/src/test/java/com/github/victools/jsonschema/module/jakarta/validation/IntegrationTest.java
index 0f5f1b3..1a2f312 100644
--- a/jsonschema-module-jakarta-validation/src/test/java/com/github/victools/jsonschema/module/jakarta/validation/IntegrationTest.java
+++ b/jsonschema-module-jakarta-validation/src/test/java/com/github/victools/jsonschema/module/jakarta/validation/IntegrationTest.java
@@ -50,11 +50,6 @@ import org.skyscreamer.jsonassert.JSONCompareMode;
  */
 public class IntegrationTest {
 
-    /**
-     * Test
-     *
-     * @throws Exception
-     */
     @Test
     public void testIntegration() throws Exception {
         // active all optional modules
@@ -83,8 +78,7 @@ public class IntegrationTest {
                 stringBuilder.append(scanner.nextLine()).append('\n');
             }
         }
-        String fileAsString = stringBuilder.toString();
-        return fileAsString;
+        return stringBuilder.toString();
 
     }
 
diff --git a/jsonschema-module-javax-validation/src/test/java/com/github/victools/jsonschema/module/javax/validation/IntegrationTest.java b/jsonschema-module-javax-validation/src/test/java/com/github/victools/jsonschema/module/javax/validation/IntegrationTest.java
index 8f08c4d..e705770 100644
--- a/jsonschema-module-javax-validation/src/test/java/com/github/victools/jsonschema/module/javax/validation/IntegrationTest.java
+++ b/jsonschema-module-javax-validation/src/test/java/com/github/victools/jsonschema/module/javax/validation/IntegrationTest.java
@@ -49,11 +49,6 @@ import org.skyscreamer.jsonassert.JSONCompareMode;
  */
 public class IntegrationTest {
 
-    /**
-     * Test
-     *
-     * @throws Exception
-     */
     @Test
     public void testIntegration() throws Exception {
         // active all optional modules
@@ -82,8 +77,7 @@ public class IntegrationTest {
                 stringBuilder.append(scanner.nextLine()).append('\n');
             }
         }
-        String fileAsString = stringBuilder.toString();
-        return fileAsString;
+        return stringBuilder.toString();
 
     }
 
diff --git a/jsonschema-module-swagger-1.5/src/test/java/com/github/victools/jsonschema/module/swagger15/IntegrationTest.java b/jsonschema-module-swagger-1.5/src/test/java/com/github/victools/jsonschema/module/swagger15/IntegrationTest.java
index f695c57..6439332 100644
--- a/jsonschema-module-swagger-1.5/src/test/java/com/github/victools/jsonschema/module/swagger15/IntegrationTest.java
+++ b/jsonschema-module-swagger-1.5/src/test/java/com/github/victools/jsonschema/module/swagger15/IntegrationTest.java
@@ -39,11 +39,6 @@ import org.skyscreamer.jsonassert.JSONCompareMode;
  */
 public class IntegrationTest {
 
-    /**
-     * Test
-     *
-     * @throws Exception
-     */
     @Test
     public void testIntegration() throws Exception {
         // active all optional modules
@@ -71,8 +66,7 @@ public class IntegrationTest {
                 stringBuilder.append(scanner.nextLine()).append('\n');
             }
         }
-        String fileAsString = stringBuilder.toString();
-        return fileAsString;
+        return stringBuilder.toString();
 
     }
 
diff --git a/jsonschema-module-swagger-1.5/src/test/java/com/github/victools/jsonschema/module/swagger15/SwaggerModuleTest.java b/jsonschema-module-swagger-1.5/src/test/java/com/github/victools/jsonschema/module/swagger15/SwaggerModuleTest.java
index ec7ed2b..7883736 100644
--- a/jsonschema-module-swagger-1.5/src/test/java/com/github/victools/jsonschema/module/swagger15/SwaggerModuleTest.java
+++ b/jsonschema-module-swagger-1.5/src/test/java/com/github/victools/jsonschema/module/swagger15/SwaggerModuleTest.java
@@ -459,15 +459,15 @@ public class SwaggerModuleTest {
         }
 
         @ApiModel
-        private class ExampleWithEmptyApiModel {
+        private static class ExampleWithEmptyApiModel {
         }
 
         @ApiModel(value = "example title")
-        private class ExampleWithApiModelTitle {
+        private static class ExampleWithApiModelTitle {
         }
 
         @ApiModel(description = "type description")
-        private class ExampleWithApiModelDescription {
+        private static class ExampleWithApiModelDescription {
         }
     }
 
diff --git a/jsonschema-module-swagger-2/src/test/java/com/github/victools/jsonschema/module/swagger2/IntegrationTest.java b/jsonschema-module-swagger-2/src/test/java/com/github/victools/jsonschema/module/swagger2/IntegrationTest.java
index 49fd230..22d38bd 100644
--- a/jsonschema-module-swagger-2/src/test/java/com/github/victools/jsonschema/module/swagger2/IntegrationTest.java
+++ b/jsonschema-module-swagger-2/src/test/java/com/github/victools/jsonschema/module/swagger2/IntegrationTest.java
@@ -79,8 +79,7 @@ public class IntegrationTest {
                 stringBuilder.append(scanner.nextLine()).append('\n');
             }
         }
-        String fileAsString = stringBuilder.toString();
-        return fileAsString;
+        return stringBuilder.toString();
 
     }
 
@@ -105,7 +104,7 @@ public class IntegrationTest {
     }
 
     @Schema(subTypes = {Reference.class, PersonReference.class})
-    static interface IReference {
+    interface IReference {
 
         String getName();
     }
diff --git a/jsonschema-module-swagger-2/src/test/java/com/github/victools/jsonschema/module/swagger2/Swagger2ModuleTest.java b/jsonschema-module-swagger-2/src/test/java/com/github/victools/jsonschema/module/swagger2/Swagger2ModuleTest.java
index 238073a..e3c78f6 100644
--- a/jsonschema-module-swagger-2/src/test/java/com/github/victools/jsonschema/module/swagger2/Swagger2ModuleTest.java
+++ b/jsonschema-module-swagger-2/src/test/java/com/github/victools/jsonschema/module/swagger2/Swagger2ModuleTest.java
@@ -31,7 +31,7 @@ import org.mockito.MockitoAnnotations;
 import org.mockito.Spy;
 
 /**
- * Test for the {@link SwaggerModule} class.
+ * Test for the {@link Swagger2Module} class.
  */
 public class Swagger2ModuleTest {