GH-644 - Polishing.
Documenter now remembers whether it has cleared the output directory so that multiple attempts to clear on one Documenter instance will not wipe the content previously generated on the same instance. All methods ultimately creating files trigger the one-time target folder wipe now. Moved file system operations into the OutputFolder abstraction. A couple of parameter renames for consistency.
This commit is contained in:
@@ -20,7 +20,6 @@ import static org.springframework.modulith.docs.Asciidoctor.*;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
@@ -71,6 +70,7 @@ import com.tngtech.archunit.core.domain.JavaClass;
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
* @author Cora Iberkleid
|
||||
* @author Tobias Haindl
|
||||
*/
|
||||
public class Documenter {
|
||||
|
||||
@@ -91,6 +91,8 @@ public class Documenter {
|
||||
private final ConfigurationProperties properties;
|
||||
private final Options options;
|
||||
|
||||
private boolean cleared;
|
||||
|
||||
private Map<ApplicationModule, Component> components;
|
||||
|
||||
/**
|
||||
@@ -113,9 +115,17 @@ public class Documenter {
|
||||
this(modules, Options.defaults());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Documenter} for the given {@link ApplicationModules} and output folder.
|
||||
*
|
||||
* @param modules must not be {@literal null}.
|
||||
* @param outputFolder must not be {@literal null} or empty.
|
||||
* @deprecated use {@link Documenter(ApplicationModules, Options)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public Documenter(ApplicationModules modules, String outputFolder) {
|
||||
|
||||
this(modules, new Options(outputFolder, true));
|
||||
this(modules, Options.defaults().withOutputFolder(outputFolder));
|
||||
|
||||
Assert.hasText(outputFolder, "Output folder must not be null or empty!");
|
||||
}
|
||||
@@ -125,6 +135,7 @@ public class Documenter {
|
||||
*
|
||||
* @param modules must not be {@literal null}.
|
||||
* @param options must not be {@literal null}.
|
||||
* @since 1.2
|
||||
*/
|
||||
public Documenter(ApplicationModules modules, Options options) {
|
||||
|
||||
@@ -146,10 +157,12 @@ public class Documenter {
|
||||
|
||||
this.container = system.addContainer(systemName, "", "");
|
||||
this.properties = new ConfigurationProperties();
|
||||
this.cleared = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Customize the output folder to write the generated files to. Defaults to {@value #DEFAULT_LOCATION}.
|
||||
* Customize the output folder to write the generated files to. Defaults to {@code spring-modulith-docs} in your build
|
||||
* systems build folder.
|
||||
*
|
||||
* @param outputFolder must not be {@literal null} or empty.
|
||||
* @return will never be {@literal null}.
|
||||
@@ -189,14 +202,12 @@ public class Documenter {
|
||||
*/
|
||||
public Documenter writeDocumentation(DiagramOptions diagramOptions, CanvasOptions canvasOptions) {
|
||||
|
||||
if (this.options.clean) {
|
||||
clearOutputFolder();
|
||||
}
|
||||
potentiallyWipeOutputFolder();
|
||||
|
||||
return writeModulesAsPlantUml(options)
|
||||
.writeIndividualModulesAsPlantUml(options)
|
||||
return writeModulesAsPlantUml(diagramOptions)
|
||||
.writeIndividualModulesAsPlantUml(diagramOptions)
|
||||
.writeModuleCanvases(canvasOptions)
|
||||
.writeAggregatingDocument(options, canvasOptions);
|
||||
.writeAggregatingDocument(diagramOptions, canvasOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,26 +222,29 @@ public class Documenter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes aggregating document called 'all-docs.adoc' that includes any existing component diagrams and canvases.
|
||||
* Writes aggregating document called {@code all-docs.adoc} that includes any existing component diagrams and
|
||||
* canvases.
|
||||
*
|
||||
* @param options must not be {@literal null}.
|
||||
* @param diagramOptions must not be {@literal null}.
|
||||
* @param canvasOptions must not be {@literal null}.
|
||||
* @return the current instance, will never be {@literal null}.
|
||||
* @since 1.2.2
|
||||
*/
|
||||
public Documenter writeAggregatingDocument(DiagramOptions options, CanvasOptions canvasOptions) {
|
||||
public Documenter writeAggregatingDocument(DiagramOptions diagramOptions, CanvasOptions canvasOptions) {
|
||||
|
||||
Assert.notNull(options, "DiagramOptions must not be null!");
|
||||
Assert.notNull(diagramOptions, "DiagramOptions must not be null!");
|
||||
Assert.notNull(canvasOptions, "CanvasOptions must not be null!");
|
||||
|
||||
potentiallyWipeOutputFolder();
|
||||
|
||||
var asciidoctor = Asciidoctor.withJavadocBase(modules, canvasOptions.getApiBase());
|
||||
var outputFolder = new OutputFolder(this.outputFolder);
|
||||
|
||||
// Get file name for module overview diagram
|
||||
var componentsFilename = options.getTargetFileName().orElse(DEFAULT_COMPONENTS_FILE);
|
||||
var componentsFilename = diagramOptions.getTargetFileName().orElse(DEFAULT_COMPONENTS_FILE);
|
||||
var componentsDoc = new StringBuilder();
|
||||
var folder = options.outputFolder;
|
||||
|
||||
if (outputFolder.contains(componentsFilename)) {
|
||||
if (folder.contains(componentsFilename)) {
|
||||
|
||||
componentsDoc
|
||||
.append(asciidoctor.renderHeadline(2, getDefaultedSystemName()))
|
||||
@@ -242,13 +256,13 @@ public class Documenter {
|
||||
var moduleDocs = modules.stream().map(it -> {
|
||||
|
||||
// Get diagram file name, e.g. module-inventory.puml
|
||||
var fileNamePattern = options.getTargetFileName().orElse(DEFAULT_MODULE_COMPONENTS_FILE);
|
||||
var fileNamePattern = diagramOptions.getTargetFileName().orElse(DEFAULT_MODULE_COMPONENTS_FILE);
|
||||
var filename = fileNamePattern.formatted(it.getName());
|
||||
var canvasFilename = canvasOptions.getTargetFileName(it.getName());
|
||||
var content = new StringBuilder();
|
||||
|
||||
content.append(outputFolder.contains(filename) ? asciidoctor.renderPlantUmlInclude(filename) : "")
|
||||
.append(outputFolder.contains(canvasFilename) ? asciidoctor.renderGeneralInclude(canvasFilename) : "");
|
||||
content.append(folder.contains(filename) ? asciidoctor.renderPlantUmlInclude(filename) : "")
|
||||
.append(folder.contains(canvasFilename) ? asciidoctor.renderGeneralInclude(canvasFilename) : "");
|
||||
|
||||
if (!content.isEmpty()) {
|
||||
|
||||
@@ -265,14 +279,7 @@ public class Documenter {
|
||||
|
||||
// Write file to all-docs.adoc
|
||||
if (!allDocs.isBlank()) {
|
||||
|
||||
var file = recreateFile("all-docs.adoc");
|
||||
|
||||
try (Writer writer = new FileWriter(file.toFile())) {
|
||||
writer.write(allDocs);
|
||||
} catch (IOException o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
}
|
||||
options.outputFolder.writeToFile("all-docs.adoc", allDocs);
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -290,20 +297,17 @@ public class Documenter {
|
||||
/**
|
||||
* Writes the PlantUML component diagram for all {@link ApplicationModules} with the given {@link DiagramOptions}.
|
||||
*
|
||||
* @param options must not be {@literal null}.
|
||||
* @param diagramOptions must not be {@literal null}.
|
||||
* @return the current instance, will never be {@literal null}.
|
||||
*/
|
||||
public Documenter writeModulesAsPlantUml(DiagramOptions options) {
|
||||
public Documenter writeModulesAsPlantUml(DiagramOptions diagramOptions) {
|
||||
|
||||
Assert.notNull(options, "Options must not be null!");
|
||||
Assert.notNull(diagramOptions, "Options must not be null!");
|
||||
|
||||
Path file = recreateFile(options.getTargetFileName().orElse(DEFAULT_COMPONENTS_FILE));
|
||||
potentiallyWipeOutputFolder();
|
||||
|
||||
try (Writer writer = new FileWriter(file.toFile())) {
|
||||
writer.write(createPlantUml(options));
|
||||
} catch (IOException o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
}
|
||||
options.outputFolder.writeToFile(diagramOptions.getTargetFileName().orElse(DEFAULT_COMPONENTS_FILE),
|
||||
createPlantUml(diagramOptions));
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -322,6 +326,8 @@ public class Documenter {
|
||||
|
||||
Assert.notNull(options, "DiagramOptions must not be null!");
|
||||
|
||||
potentiallyWipeOutputFolder();
|
||||
|
||||
modules.forEach(it -> writeModuleAsPlantUml(it, options));
|
||||
|
||||
return this;
|
||||
@@ -353,6 +359,8 @@ public class Documenter {
|
||||
Assert.notNull(module, "Module must not be null!");
|
||||
Assert.notNull(options, "Options must not be null!");
|
||||
|
||||
potentiallyWipeOutputFolder();
|
||||
|
||||
var view = createComponentView(options, module);
|
||||
view.setTitle(options.defaultDisplayName.apply(module));
|
||||
|
||||
@@ -375,25 +383,20 @@ public class Documenter {
|
||||
/**
|
||||
* Writes all module canvases using the given {@link DiagramOptions}.
|
||||
*
|
||||
* @param options must not be {@literal null}.
|
||||
* @param canvasOptions must not be {@literal null}.
|
||||
* @return the current instance, will never be {@literal null}.
|
||||
*/
|
||||
public Documenter writeModuleCanvases(CanvasOptions options) {
|
||||
public Documenter writeModuleCanvases(CanvasOptions canvasOptions) {
|
||||
|
||||
Assert.notNull(options, "CanvasOptions must not be null!");
|
||||
Assert.notNull(canvasOptions, "CanvasOptions must not be null!");
|
||||
|
||||
potentiallyWipeOutputFolder();
|
||||
|
||||
modules.forEach(module -> {
|
||||
|
||||
var filename = options.getTargetFileName(module.getName());
|
||||
var file = recreateFile(filename);
|
||||
var filename = canvasOptions.getTargetFileName(module.getName());
|
||||
|
||||
try (FileWriter writer = new FileWriter(file.toFile())) {
|
||||
|
||||
writer.write(toModuleCanvas(module, options));
|
||||
|
||||
} catch (IOException o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
}
|
||||
options.outputFolder.writeToFile(filename, toModuleCanvas(module, canvasOptions));
|
||||
});
|
||||
|
||||
return this;
|
||||
@@ -552,19 +555,11 @@ public class Documenter {
|
||||
.findFirst().ifPresent(view::remove);
|
||||
}
|
||||
|
||||
private Documenter writeViewAsPlantUml(ComponentView view, String filename, DiagramOptions options) {
|
||||
private Documenter writeViewAsPlantUml(ComponentView view, String filename, DiagramOptions diagramOptions) {
|
||||
|
||||
Path file = recreateFile(filename);
|
||||
options.outputFolder.writeToFile(filename, render(view, diagramOptions));
|
||||
|
||||
try (Writer writer = new FileWriter(file.toFile())) {
|
||||
|
||||
writer.write(render(view, options));
|
||||
|
||||
return this;
|
||||
|
||||
} catch (IOException o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private String render(ComponentView view, DiagramOptions options) {
|
||||
@@ -610,34 +605,13 @@ public class Documenter {
|
||||
.createComponentView(container, prefix + options.toString(), "");
|
||||
}
|
||||
|
||||
private void clearOutputFolder() {
|
||||
private void potentiallyWipeOutputFolder() {
|
||||
|
||||
Path outputPath = Paths.get(options.outputFolder);
|
||||
if (!outputPath.toFile().exists()) {
|
||||
return;
|
||||
}
|
||||
if (options.clean && !cleared) {
|
||||
|
||||
try (Stream<Path> paths = Files.walk(outputPath)) {
|
||||
paths.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
|
||||
} catch (IOException o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
}
|
||||
}
|
||||
options.outputFolder.deleteIfExists();
|
||||
|
||||
private Path recreateFile(String name) {
|
||||
|
||||
try {
|
||||
|
||||
var outputFolder = options.outputFolder;
|
||||
|
||||
Files.createDirectories(Paths.get(outputFolder));
|
||||
Path filePath = Paths.get(outputFolder, name);
|
||||
Files.deleteIfExists(filePath);
|
||||
|
||||
return Files.createFile(filePath);
|
||||
|
||||
} catch (IOException o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
this.cleared = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -678,15 +652,6 @@ public class Documenter {
|
||||
return options.hideEmptyLines && types.isEmpty() ? "" : writeTableRow(header, mapper.apply(types));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default output directory based on the detected build system.
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
private static String getDefaultOutputDirectory() {
|
||||
return (new File("pom.xml").exists() ? "target" : "build").concat("/").concat(DEFAULT_LOCATION);
|
||||
}
|
||||
|
||||
private String getDefaultedSystemName() {
|
||||
return modules.getSystemName().orElse("Modules");
|
||||
}
|
||||
@@ -1277,39 +1242,35 @@ public class Documenter {
|
||||
|
||||
public static class Options {
|
||||
|
||||
private static final String DEFAULT_LOCATION = (new File("pom.xml").exists() ? "target" : "build")
|
||||
.concat("/spring-modulith-docs");
|
||||
|
||||
private final String outputFolder;
|
||||
|
||||
private final OutputFolder outputFolder;
|
||||
private final boolean clean;
|
||||
|
||||
/**
|
||||
* @param outputFolder the folder to write the files to, can be {@literal null}.
|
||||
* @param clean whether to clean the target directory on rendering.
|
||||
*/
|
||||
private Options(@Nullable String outputFolder, boolean clean) {
|
||||
private Options(OutputFolder outputFolder, boolean clean) {
|
||||
|
||||
this.outputFolder = outputFolder == null ? DEFAULT_LOCATION : outputFolder;
|
||||
this.outputFolder = outputFolder;
|
||||
this.clean = clean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a default {@link Options} instance configuring a default output folder based on the detected build tool (see {@link Options#DEFAULT_LOCATION}).
|
||||
* Use {@link #withOutputFolder(String)} if you want to customize the output folder.
|
||||
* Per default the output folder is wiped before any files are written to it.
|
||||
* Use {@link #withoutClean()} to disable cleaning of the output folder.
|
||||
* Creates a default {@link Options} instance configuring a default output folder based on the detected build tool
|
||||
* (see {@link OutputFolder#DEFAULT_LOCATION}). Use {@link #withOutputFolder(String)} if you want to customize the
|
||||
* output folder. By default, the output folder is wiped before any files are written to it. Use
|
||||
* {@link #withoutClean()} to disable cleaning of the output folder.
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
* @see #withoutClean()
|
||||
* @see #withOutputFolder(String)
|
||||
*/
|
||||
public static Options defaults() {
|
||||
return new Options(DEFAULT_LOCATION, true);
|
||||
return new Options(OutputFolder.forDefaultLocation(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the cleaning of the output folder before any file is written.
|
||||
* Disables the cleaning of the output folder before any files are written.
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
@@ -1318,15 +1279,111 @@ public class Documenter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the output folder for the created files.
|
||||
* The given directory is wiped before any files are written to it.
|
||||
* Configures the output folder for the created files. The given directory is wiped before any files are written to
|
||||
* it.
|
||||
*
|
||||
* @param folder if null the default location based on the detected build tool will be used (see {@link Options#DEFAULT_LOCATION}).
|
||||
* The given folder will be created if it does not exist already. Existing folders are supported as well.
|
||||
* @param folder if null the default location based on the detected build tool will be used (see
|
||||
* {@link OutputFolder#DEFAULT_LOCATION}). The given folder will be created if it does not exist already.
|
||||
* Existing folders are supported as well.
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
public Options withOutputFolder(String folder) {
|
||||
return new Options(folder, clean);
|
||||
public Options withOutputFolder(@Nullable String folder) {
|
||||
return new Options(OutputFolder.forLocation(folder), clean);
|
||||
}
|
||||
|
||||
OutputFolder getOutputFolder() {
|
||||
return outputFolder;
|
||||
}
|
||||
}
|
||||
|
||||
static class OutputFolder {
|
||||
|
||||
private static final String DEFAULT_LOCATION = (new File("pom.xml").exists() ? "target" : "build")
|
||||
.concat("/spring-modulith-docs");
|
||||
|
||||
private final String path;
|
||||
|
||||
private OutputFolder(String path) {
|
||||
|
||||
this.path = path;
|
||||
|
||||
try {
|
||||
Files.createDirectories(Path.of(path));
|
||||
} catch (IOException o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
}
|
||||
}
|
||||
|
||||
static OutputFolder forLocation(@Nullable String location) {
|
||||
return new OutputFolder(location == null ? DEFAULT_LOCATION : location);
|
||||
}
|
||||
|
||||
static OutputFolder forDefaultLocation() {
|
||||
return new OutputFolder(DEFAULT_LOCATION);
|
||||
}
|
||||
|
||||
boolean contains(String filename) {
|
||||
return Files.exists(Paths.get(path, filename));
|
||||
}
|
||||
|
||||
OutputFolder deleteIfExists() {
|
||||
|
||||
var path = Path.of(this.path);
|
||||
|
||||
if (!Files.exists(path)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
Files.walk(path)
|
||||
.sorted(Comparator.reverseOrder())
|
||||
.map(Path::toFile)
|
||||
.forEach(File::delete);
|
||||
|
||||
} catch (IOException o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
void writeToFile(String name, String content) {
|
||||
|
||||
var path = deleteIfExists(name).createFile(name);
|
||||
|
||||
try (FileWriter writer = new FileWriter(path.toFile())) {
|
||||
|
||||
writer.write(content);
|
||||
|
||||
} catch (IOException o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
}
|
||||
}
|
||||
|
||||
private OutputFolder deleteIfExists(String name) {
|
||||
|
||||
try {
|
||||
Files.deleteIfExists(Path.of(path, name));
|
||||
} catch (IOException o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private Path createFile(String name) {
|
||||
|
||||
var path = Path.of(this.path);
|
||||
|
||||
try {
|
||||
|
||||
Files.createDirectories(path);
|
||||
return Files.createFile(path.resolve(name));
|
||||
|
||||
} catch (IOException o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1343,17 +1400,4 @@ public class Documenter {
|
||||
@Override
|
||||
protected void endContainerBoundary(ModelView view, IndentingWriter writer) {};
|
||||
};
|
||||
|
||||
private static class OutputFolder {
|
||||
|
||||
private final String path;
|
||||
|
||||
OutputFolder(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
boolean contains(String filename) {
|
||||
return Files.exists(Paths.get(path, filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Comparator;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -33,7 +33,6 @@ import org.springframework.modulith.core.ApplicationModules;
|
||||
import org.springframework.modulith.core.DependencyType;
|
||||
import org.springframework.modulith.docs.Documenter.DiagramOptions;
|
||||
import org.springframework.modulith.docs.Documenter.Options;
|
||||
import org.springframework.util.function.ThrowingConsumer;
|
||||
|
||||
import com.acme.myproject.Application;
|
||||
|
||||
@@ -42,6 +41,7 @@ import com.acme.myproject.Application;
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
* @author Cora Iberkleid
|
||||
* @author Tobias Haindl
|
||||
*/
|
||||
class DocumenterTest {
|
||||
|
||||
@@ -79,12 +79,9 @@ class DocumenterTest {
|
||||
@Test
|
||||
void customizesOutputLocation() throws Exception {
|
||||
|
||||
String customOutputFolder = "build/spring-modulith";
|
||||
Path path = Paths.get(customOutputFolder);
|
||||
doWith("target/custom-spring-modulith", (path, documenter) -> {
|
||||
|
||||
doWith(path, it -> {
|
||||
|
||||
new Documenter(ApplicationModules.of(Application.class), customOutputFolder).writeModuleCanvases();
|
||||
documenter.writeModuleCanvases();
|
||||
|
||||
assertThat(Files.list(path)).isNotEmpty();
|
||||
assertThat(path).exists();
|
||||
@@ -94,22 +91,20 @@ class DocumenterTest {
|
||||
@Test // GH-638
|
||||
void createsAggregatingDocumentOnlyIfPartialsExist() throws Exception {
|
||||
|
||||
var customOutputFolder = "build/spring-modulith";
|
||||
var path = Paths.get(customOutputFolder);
|
||||
var documenter = new Documenter(ApplicationModules.of(Application.class), customOutputFolder);
|
||||
|
||||
doWith(path, it -> {
|
||||
doWith("build/spring-modulith", (path, documenter) -> {
|
||||
|
||||
// all-docs.adoc should be created
|
||||
documenter.writeDocumentation();
|
||||
|
||||
var numberOfModules = documenter.getModules().stream().count();
|
||||
|
||||
// 2 per module (PlantUML + Canvas) + component overview + aggregating doc
|
||||
var expectedFiles = documenter.getModules().stream().count() * 2 + 2;
|
||||
var expectedFiles = numberOfModules * 2 + 2;
|
||||
|
||||
// 3 per module (headline + PlantUML + Canvas) + component headline + component PlantUML
|
||||
var expectedLines = documenter.getModules().stream().count() * 3 + 2;
|
||||
var expectedLines = numberOfModules * 3 + 2;
|
||||
|
||||
assertThat(Files.walk(it).filter(Files::isRegularFile).count())
|
||||
assertThat(Files.walk(path).filter(Files::isRegularFile).count())
|
||||
.isEqualTo(expectedFiles);
|
||||
|
||||
assertThat(path.resolve("all-docs.adoc")).exists().satisfies(doc -> {
|
||||
@@ -123,15 +118,11 @@ class DocumenterTest {
|
||||
@Test // GH-638
|
||||
void doesNotCreateAggregatingDocumentIfNoPartialsExist() throws Exception {
|
||||
|
||||
var customOutputFolder = "build/spring-modulith";
|
||||
var path = Paths.get(customOutputFolder);
|
||||
doWith("build/spring-modulith", (path, documenter) -> {
|
||||
|
||||
doWith(path, it -> {
|
||||
documenter.writeDocumentation();
|
||||
|
||||
var documenter = new Documenter(ApplicationModules.of(Application.class), customOutputFolder)
|
||||
.writeDocumentation();
|
||||
|
||||
deleteDirectoryContents(it);
|
||||
deleteDirectoryContents(path);
|
||||
|
||||
documenter.writeAggregatingDocument();
|
||||
|
||||
@@ -141,32 +132,37 @@ class DocumenterTest {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCleanOutputLocation(@TempDir Path outputDirectory) throws IOException {
|
||||
@Test // GH-644
|
||||
void cleansOutputDirectoryByDefault(@TempDir Path outputDirectory) {
|
||||
|
||||
var filePath = createTestFile(outputDirectory);
|
||||
var nestedFiledPath = createTestFileInSubdirectory(outputDirectory);
|
||||
doWith(outputDirectory.toString(), (path, documenter) -> {
|
||||
|
||||
new Documenter(ApplicationModules.of(Application.class), outputDirectory.toString()).writeDocumentation();
|
||||
var filePath = createTestFile(path);
|
||||
var nestedFiledPath = createTestFileInSubdirectory(path);
|
||||
|
||||
documenter.writeDocumentation();
|
||||
|
||||
assertThat(filePath).doesNotExist();
|
||||
assertThat(nestedFiledPath).doesNotExist();
|
||||
assertThat(Files.list(path)).isNotEmpty();
|
||||
});
|
||||
|
||||
assertThat(filePath).doesNotExist();
|
||||
assertThat(nestedFiledPath).doesNotExist();
|
||||
assertThat(Files.list(outputDirectory)).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotCleanOutputLocation(@TempDir Path outputDirectory) throws IOException {
|
||||
|
||||
var filePath = createTestFile(outputDirectory);
|
||||
var nestedFiledPath = createTestFileInSubdirectory(outputDirectory);
|
||||
@Test // GH-644
|
||||
void doesNotCleanOutputDirectoryIfConfigured(@TempDir Path outputDirectory) throws IOException {
|
||||
|
||||
new Documenter(ApplicationModules.of(Application.class),
|
||||
Options.defaults().withOutputFolder(outputDirectory.toString()).withoutClean())
|
||||
.writeDocumentation();
|
||||
doWith(outputDirectory.toString(), it -> it.withoutClean(), (path, documenter) -> {
|
||||
|
||||
assertThat(filePath).exists();
|
||||
assertThat(nestedFiledPath).exists();
|
||||
assertThat(Files.list(outputDirectory)).isNotEmpty();
|
||||
var filePath = createTestFile(path);
|
||||
var nestedFiledPath = createTestFileInSubdirectory(path);
|
||||
|
||||
documenter.writeDocumentation();
|
||||
|
||||
assertThat(filePath).exists();
|
||||
assertThat(nestedFiledPath).exists();
|
||||
assertThat(Files.list(path)).isNotEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
private static Path createTestFile(Path tempDir) throws IOException {
|
||||
@@ -193,18 +189,26 @@ class DocumenterTest {
|
||||
}
|
||||
}
|
||||
|
||||
private static void deleteDirectory(Path path) throws IOException {
|
||||
|
||||
deleteDirectoryContents(path);
|
||||
Files.deleteIfExists(path);
|
||||
private static void doWith(String path, ThrowingBiConsumer<Path, Documenter> consumer) {
|
||||
doWith(path, Function.identity(), consumer);
|
||||
}
|
||||
|
||||
private static void doWith(Path path, ThrowingConsumer<Path> consumer) throws Exception {
|
||||
private static void doWith(String path, Function<Options, Options> customizer,
|
||||
ThrowingBiConsumer<Path, Documenter> consumer) {
|
||||
|
||||
var options = customizer.apply(Options.defaults().withOutputFolder(path));
|
||||
var modules = ApplicationModules.of(Application.class);
|
||||
|
||||
try {
|
||||
consumer.accept(path);
|
||||
consumer.accept(Path.of(path), new Documenter(modules, options));
|
||||
} catch (Exception o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
} finally {
|
||||
deleteDirectory(path);
|
||||
options.getOutputFolder().deleteIfExists();
|
||||
}
|
||||
}
|
||||
|
||||
private interface ThrowingBiConsumer<T, S> {
|
||||
void accept(T t, S s) throws Exception;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user