GH-1192 - Migrate code base to jSpecify for nullness verification.
This commit is contained in:
@@ -25,9 +25,9 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.modulith.core.ApplicationModule;
|
||||
import org.springframework.modulith.core.ApplicationModuleDependency;
|
||||
import org.springframework.modulith.core.ApplicationModules;
|
||||
|
||||
@@ -23,9 +23,9 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.modulith.core.ApplicationModule;
|
||||
import org.springframework.modulith.docs.ConfigurationProperties.ConfigurationProperty;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -124,7 +124,6 @@ class ConfigurationProperties implements Iterable<ConfigurationProperty> {
|
||||
static record ConfigurationProperty(String name, @Nullable String description, String type, String sourceType,
|
||||
@Nullable String defaultValue) {
|
||||
|
||||
@SuppressWarnings("null")
|
||||
static Stream<ConfigurationProperty> of(Map<String, Object> source) {
|
||||
|
||||
String sourceType = getAsString(source, "sourceType");
|
||||
@@ -133,9 +132,9 @@ class ConfigurationProperties implements Iterable<ConfigurationProperty> {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
ConfigurationProperty property = new ConfigurationProperty(getAsString(source, "name"),
|
||||
ConfigurationProperty property = new ConfigurationProperty(getRequiredAsString(source, "name"),
|
||||
getAsString(source, "description"),
|
||||
getAsString(source, "type"),
|
||||
getRequiredAsString(source, "type"),
|
||||
sourceType,
|
||||
getAsString(source, "defaultValue"));
|
||||
|
||||
@@ -146,6 +145,15 @@ class ConfigurationProperties implements Iterable<ConfigurationProperty> {
|
||||
return StringUtils.hasText(sourceType);
|
||||
}
|
||||
|
||||
private static String getRequiredAsString(Map<String, Object> source, String key) {
|
||||
|
||||
var value = getAsString(source, key);
|
||||
|
||||
Assert.notNull(value, "No value found for key %s in %s!".formatted(key, source));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private static @Nullable String getAsString(Map<String, Object> source, String key) {
|
||||
|
||||
Object value = source.get(key);
|
||||
|
||||
@@ -36,7 +36,8 @@ import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.lang.Contract;
|
||||
import org.springframework.modulith.core.ApplicationModule;
|
||||
import org.springframework.modulith.core.ApplicationModules;
|
||||
import org.springframework.modulith.core.DependencyDepth;
|
||||
@@ -98,7 +99,7 @@ public class Documenter {
|
||||
|
||||
private boolean cleared;
|
||||
|
||||
private Map<ApplicationModule, Component> components;
|
||||
private @Nullable Map<ApplicationModule, Component> components;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Documenter} for the {@link ApplicationModules} created for the given modulith type in the
|
||||
@@ -223,6 +224,7 @@ public class Documenter {
|
||||
* @return the current instance, will never be {@literal null}.
|
||||
* @since 1.2.2
|
||||
*/
|
||||
@Contract("_, _ -> this")
|
||||
public Documenter writeAggregatingDocument(DiagramOptions diagramOptions, CanvasOptions canvasOptions) {
|
||||
|
||||
Assert.notNull(diagramOptions, "DiagramOptions must not be null!");
|
||||
@@ -485,18 +487,19 @@ public class Documenter {
|
||||
.forEach(it -> it.addTags(DependencyType.USES_COMPONENT.toString()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("null")
|
||||
private Map<ApplicationModule, Component> getComponents(DiagramOptions options) {
|
||||
|
||||
if (components == null) {
|
||||
if (this.components == null) {
|
||||
|
||||
this.components = modules.stream() //
|
||||
.collect(Collectors.toMap(Function.identity(),
|
||||
it -> container.addComponent(options.defaultDisplayName.apply(it), "", "Module")));
|
||||
|
||||
this.components.forEach((key, value) -> addDependencies(key, value, options));
|
||||
components.forEach((key, value) -> addDependencies(key, value, options));
|
||||
}
|
||||
|
||||
return components;
|
||||
return this.components;
|
||||
}
|
||||
|
||||
private void addComponentsToView(ApplicationModule module, ComponentView view, DiagramOptions options) {
|
||||
@@ -643,6 +646,11 @@ public class Documenter {
|
||||
Styles styles) {
|
||||
|
||||
var component = components.get(module);
|
||||
|
||||
if (component == null) {
|
||||
throw new IllegalStateException("Couldn't find component for module %s!".formatted(module));
|
||||
}
|
||||
|
||||
var selector = options.colorSelector;
|
||||
|
||||
// Apply custom color if configured
|
||||
@@ -1061,6 +1069,7 @@ public class Documenter {
|
||||
return new CanvasOptions(groupers, apiBase, targetFileName, hideInternals, hideEmptyLines);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
String getApiBase() {
|
||||
return apiBase;
|
||||
}
|
||||
@@ -1083,7 +1092,10 @@ public class Documenter {
|
||||
|
||||
// Wipe entries without any beans
|
||||
new HashSet<>(result.keySet()).forEach(key -> {
|
||||
if (result.get(key).isEmpty()) {
|
||||
|
||||
var value = result.get(key);
|
||||
|
||||
if (value != null && value.isEmpty()) {
|
||||
result.remove(key);
|
||||
}
|
||||
});
|
||||
@@ -1161,10 +1173,10 @@ public class Documenter {
|
||||
*
|
||||
* @param name must not be {@literal null} or empty.
|
||||
* @param predicate must not be {@literal null}.
|
||||
* @param description must not be {@literal null} or empty.
|
||||
* @param description can be {@literal null}.
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
public static Grouping of(String name, Predicate<SpringBean> predicate, String description) {
|
||||
public static Grouping of(String name, Predicate<SpringBean> predicate, @Nullable String description) {
|
||||
return new Grouping(name, predicate, description);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,9 +23,9 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.boot.json.BasicJsonParser;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.modulith.docs.metadata.MethodMetadata;
|
||||
import org.springframework.modulith.docs.metadata.TypeMetadata;
|
||||
import org.springframework.modulith.docs.util.BuildSystemUtils;
|
||||
@@ -134,28 +134,39 @@ class SpringModulithDocumentationSource implements DocumentationSource {
|
||||
@SuppressWarnings("unchecked")
|
||||
private static TypeMetadata typeMetadata(Map<String, Object> source) {
|
||||
|
||||
var methods = source.containsKey("methods")
|
||||
? ((List<Map<String, Object>>) source.get("methods")).stream()
|
||||
.map(SpringModulithDocumentationSource::methodMetadata)
|
||||
.toList()
|
||||
var sourceMethods = (List<Map<String, Object>>) source.get("methods");
|
||||
|
||||
var methods = sourceMethods != null
|
||||
? sourceMethods.stream().map(SpringModulithDocumentationSource::methodMetadata).toList()
|
||||
: Collections.<MethodMetadata> emptyList();
|
||||
|
||||
return new TypeMetadata(
|
||||
source.get("name").toString(),
|
||||
getString(source, "comment"),
|
||||
methods);
|
||||
var name = source.get("name");
|
||||
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("Source map does not contain a name entry! %s".formatted(source));
|
||||
}
|
||||
|
||||
return new TypeMetadata(name.toString(), getString(source, "comment"), methods);
|
||||
}
|
||||
|
||||
private static MethodMetadata methodMetadata(Map<String, Object> source) {
|
||||
|
||||
return new MethodMetadata(
|
||||
source.get("name").toString(),
|
||||
source.get("signature").toString(),
|
||||
getString(source, "comment"));
|
||||
var name = source.get("name");
|
||||
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("No name found in source map! %s".formatted(source));
|
||||
}
|
||||
|
||||
var signature = source.get("signature");
|
||||
|
||||
if (signature == null) {
|
||||
throw new IllegalArgumentException("No signature found in source map! %s".formatted(source));
|
||||
}
|
||||
|
||||
return new MethodMetadata(name.toString(), signature.toString(), getString(source, "comment"));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getString(Map<String, Object> source, String key) {
|
||||
private static @Nullable String getString(Map<String, Object> source, String key) {
|
||||
|
||||
Object result = source.get(key);
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.modulith.docs.metadata;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Metadata about a Java type.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Documentation support for Spring Modulith.
|
||||
*/
|
||||
@org.springframework.lang.NonNullApi
|
||||
@org.jspecify.annotations.NullMarked
|
||||
package org.springframework.modulith.docs;
|
||||
|
||||
Reference in New Issue
Block a user