Skip to content

Commit 31d60b7

Browse files
committed
Split API reports by module and package
1 parent 7030418 commit 31d60b7

File tree

7 files changed

+142
-67
lines changed

7 files changed

+142
-67
lines changed

documentation/documentation.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ dependencies {
5555
// Pull in all "modular projects" to ensure that they are included
5656
// in reports generated by the ApiReportGenerator.
5757
modularProjects.forEach { apiReport(it) }
58+
apiReport(libs.openTestReporting.tooling.spi)
5859

5960
// Pull in all "mavenized projects" to ensure that they are included
6061
// in the generation of build provenance attestation.

documentation/src/tools/java/org/junit/api/tools/AbstractApiReportWriter.java

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@
1111
package org.junit.api.tools;
1212

1313
import static java.lang.String.format;
14+
import static java.util.stream.Collectors.groupingBy;
15+
import static java.util.stream.Collectors.toList;
1416

1517
import java.io.PrintWriter;
1618
import java.util.List;
1719
import java.util.Set;
20+
import java.util.TreeMap;
1821

1922
import org.apiguardian.api.API.Status;
2023

@@ -49,12 +52,22 @@ public void printDeclarationInfo(PrintWriter out, Set<Status> statuses) {
4952
protected void printDeclarationSection(Set<Status> statuses, Status status, List<Declaration> declarations,
5053
PrintWriter out) {
5154
printDeclarationSectionHeader(statuses, status, declarations, out);
52-
if (!declarations.isEmpty()) {
53-
printDeclarationTableHeader(out);
54-
declarations.forEach(it -> printDeclarationTableRow(it, out));
55-
printDeclarationTableFooter(out);
56-
out.println();
57-
}
55+
declarations.stream() //
56+
.collect(groupingBy(Declaration::moduleName, TreeMap::new, toList())) //
57+
.forEach((moduleName, moduleDeclarations) -> {
58+
out.println(h4("Module " + moduleName));
59+
out.println();
60+
moduleDeclarations.stream() //
61+
.collect(groupingBy(Declaration::packageName, TreeMap::new, toList())) //
62+
.forEach((packageName, packageDeclarations) -> {
63+
out.println(h5("Package " + packageName));
64+
out.println();
65+
printDeclarationTableHeader(out);
66+
packageDeclarations.forEach(it -> printDeclarationTableRow(it, out));
67+
printDeclarationTableFooter(out);
68+
out.println();
69+
});
70+
});
5871
}
5972

6073
protected void printDeclarationSectionHeader(Set<Status> statuses, Status status, List<Declaration> declarations,
@@ -74,6 +87,10 @@ protected void printDeclarationSectionHeader(Set<Status> statuses, Status status
7487

7588
protected abstract String h2(String header);
7689

90+
protected abstract String h4(String header);
91+
92+
protected abstract String h5(String header);
93+
7794
protected abstract String code(String element);
7895

7996
protected abstract String italic(String element);

documentation/src/tools/java/org/junit/api/tools/ApiReportGenerator.java

Lines changed: 52 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@
1010

1111
package org.junit.api.tools;
1212

13+
import static java.nio.charset.StandardCharsets.UTF_8;
1314
import static java.util.stream.Collectors.toCollection;
1415

1516
import java.io.BufferedOutputStream;
17+
import java.io.File;
1618
import java.io.IOException;
1719
import java.io.OutputStream;
1820
import java.io.PrintWriter;
1921
import java.io.UncheckedIOException;
22+
import java.lang.module.ModuleFinder;
2023
import java.nio.file.Files;
2124
import java.nio.file.Path;
2225
import java.util.ArrayList;
@@ -25,6 +28,7 @@
2528
import java.util.EnumSet;
2629
import java.util.List;
2730
import java.util.Map;
31+
import java.util.Set;
2832
import java.util.SortedSet;
2933
import java.util.TreeSet;
3034
import java.util.stream.Stream;
@@ -52,30 +56,30 @@ public static void main(String... args) {
5256
// CAUTION: The output produced by this method is used to
5357
// generate a table in the User Guide.
5458

55-
var reportGenerator = new ApiReportGenerator();
59+
try (var scanResult = scanClasspath()) {
5660

57-
// scan all types below "org.junit" package
58-
var apiReport = reportGenerator.generateReport("org.junit");
59-
60-
// ApiReportWriter reportWriter = new MarkdownApiReportWriter(apiReport);
61-
ApiReportWriter reportWriter = new AsciidocApiReportWriter(apiReport);
62-
// ApiReportWriter reportWriter = new HtmlApiReportWriter(apiReport);
63-
64-
// reportWriter.printReportHeader(new PrintWriter(System.out, true));
65-
66-
// Print report for all Usage enum constants
67-
// reportWriter.printDeclarationInfo(new PrintWriter(System.out, true), EnumSet.allOf(Status.class));
68-
69-
// Print report only for specific Status constants, defaults to only EXPERIMENTAL
70-
parseArgs(args).forEach((status, opener) -> {
71-
try (var stream = opener.openStream()) {
72-
var writer = new PrintWriter(stream == null ? System.out : stream, true);
73-
reportWriter.printDeclarationInfo(writer, EnumSet.of(status));
74-
}
75-
catch (IOException e) {
76-
throw new UncheckedIOException("Failed to write report", e);
77-
}
78-
});
61+
var apiReport = generateReport(scanResult);
62+
63+
// ApiReportWriter reportWriter = new MarkdownApiReportWriter(apiReport);
64+
ApiReportWriter reportWriter = new AsciidocApiReportWriter(apiReport);
65+
// ApiReportWriter reportWriter = new HtmlApiReportWriter(apiReport);
66+
67+
// reportWriter.printReportHeader(new PrintWriter(System.out, true));
68+
69+
// Print report for all Usage enum constants
70+
// reportWriter.printDeclarationInfo(new PrintWriter(System.out, true), EnumSet.allOf(Status.class));
71+
72+
// Print report only for specific Status constants, defaults to only EXPERIMENTAL
73+
parseArgs(args).forEach((status, opener) -> {
74+
try (var stream = opener.openStream()) {
75+
var writer = new PrintWriter(stream == null ? System.out : stream, true, UTF_8);
76+
reportWriter.printDeclarationInfo(writer, EnumSet.of(status));
77+
}
78+
catch (IOException e) {
79+
throw new UncheckedIOException("Failed to write report", e);
80+
}
81+
});
82+
}
7983
}
8084

8185
// -------------------------------------------------------------------------
@@ -102,45 +106,48 @@ private interface StreamOpener {
102106
OutputStream openStream() throws IOException;
103107
}
104108

105-
ApiReport generateReport(String... packages) {
109+
private static ApiReport generateReport(ScanResult scanResult) {
106110
Map<Status, List<Declaration>> declarations = new EnumMap<>(Status.class);
107111
for (var status : Status.values()) {
108112
declarations.put(status, new ArrayList<>());
109113
}
110114

111-
try (var scanResult = scanClasspath(packages)) {
112-
113-
var types = collectTypes(scanResult);
114-
types.stream() //
115-
.map(Declaration.Type::new) //
116-
.forEach(type -> declarations.get(type.status()).add(type));
115+
var types = collectTypes(scanResult);
116+
types.stream() //
117+
.map(Declaration.Type::new) //
118+
.forEach(type -> declarations.get(type.status()).add(type));
117119

118-
collectMethods(scanResult) //
119-
.map(Declaration.Method::new) //
120-
.filter(method -> !declarations.get(method.status()) //
121-
.contains(new Declaration.Type(method.classInfo()))) //
122-
.forEach(method -> {
123-
types.add(method.classInfo());
124-
declarations.get(method.status()).add(method);
125-
});
120+
collectMethods(scanResult) //
121+
.map(Declaration.Method::new) //
122+
.filter(method -> !declarations.get(method.status()) //
123+
.contains(new Declaration.Type(method.classInfo()))) //
124+
.forEach(method -> {
125+
types.add(method.classInfo());
126+
declarations.get(method.status()).add(method);
127+
});
126128

127-
declarations.values().forEach(list -> list.sort(null));
129+
declarations.values().forEach(list -> list.sort(null));
128130

129-
return new ApiReport(types, declarations);
130-
}
131+
return new ApiReport(types, declarations);
131132
}
132133

133-
private static ScanResult scanClasspath(String[] packages) {
134+
private static ScanResult scanClasspath() {
135+
// scan all types below "org.junit" package
134136
var classGraph = new ClassGraph() //
135-
.acceptPackages(packages) //
136-
.rejectPackages("*.shadow.*") //
137+
.acceptPackages("org.junit") //
138+
.rejectPackages("*.shadow.*", "org.opentest4j.*") //
137139
.disableNestedJarScanning() //
138140
.enableClassInfo() //
139141
.enableMethodInfo() //
140142
.enableAnnotationInfo(); //
141143
var apiClasspath = System.getProperty("api.classpath");
142144
if (apiClasspath != null) {
143-
classGraph = classGraph.overrideClasspath(apiClasspath);
145+
var paths = Arrays.stream(apiClasspath.split(File.pathSeparator)).map(Path::of).toArray(Path[]::new);
146+
var bootLayer = ModuleLayer.boot();
147+
var configuration = bootLayer.configuration().resolveAndBind(ModuleFinder.of(), ModuleFinder.of(paths),
148+
Set.of());
149+
var layer = bootLayer.defineModulesWithOneLoader(configuration, ClassLoader.getPlatformClassLoader());
150+
classGraph = classGraph.overrideModuleLayers(layer);
144151
}
145152
return classGraph.scan();
146153
}

documentation/src/tools/java/org/junit/api/tools/AsciidocApiReportWriter.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
*/
1818
class AsciidocApiReportWriter extends AbstractApiReportWriter {
1919

20-
private static final String ASCIIDOC_FORMAT = "| %-52s | %-" + NAME_COLUMN_WIDTH + "s | %-12s%n";
20+
private static final String ASCIIDOC_FORMAT = "|%-" + NAME_COLUMN_WIDTH + "s | %-12s%n";
2121

2222
AsciidocApiReportWriter(ApiReport apiReport) {
2323
super(apiReport);
@@ -33,6 +33,16 @@ protected String h2(String header) {
3333
return "== " + header;
3434
}
3535

36+
@Override
37+
protected String h4(String header) {
38+
return "[discrete]%n==== %s".formatted(header);
39+
}
40+
41+
@Override
42+
protected String h5(String header) {
43+
return "[discrete]%n===== %s".formatted(header);
44+
}
45+
3646
@Override
3747
protected String code(String element) {
3848
return "`" + element + "`";
@@ -45,16 +55,16 @@ protected String italic(String element) {
4555

4656
@Override
4757
protected void printDeclarationTableHeader(PrintWriter out) {
58+
out.println("[cols=\"99,1\"]");
4859
out.println("|===");
49-
out.printf(ASCIIDOC_FORMAT, "Package Name", "Name", "Since");
60+
out.printf(ASCIIDOC_FORMAT, "Name", "Since");
5061
out.println();
5162
}
5263

5364
@Override
5465
protected void printDeclarationTableRow(Declaration declaration, PrintWriter out) {
5566
out.printf(ASCIIDOC_FORMAT, //
56-
code(declaration.packageName()), //
57-
code(declaration.name()) + " " + italic("(" + declaration.kind() + ")"), //
67+
code(declaration.name().replace(".", ".&ZeroWidthSpace;")) + " " + italic("(" + declaration.kind() + ")"), //
5868
code(declaration.since()) //
5969
);
6070
}

documentation/src/tools/java/org/junit/api/tools/Declaration.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
sealed interface Declaration extends Comparable<Declaration> {
2626

27+
String moduleName();
28+
2729
String packageName();
2830

2931
String fullName();
@@ -43,6 +45,11 @@ default int compareTo(Declaration o) {
4345

4446
record Type(ClassInfo classInfo) implements Declaration {
4547

48+
@Override
49+
public String moduleName() {
50+
return classInfo.getModuleRef().getName();
51+
}
52+
4653
@Override
4754
public String packageName() {
4855
return classInfo.getPackageName();
@@ -55,7 +62,8 @@ public String fullName() {
5562

5663
@Override
5764
public String name() {
58-
return getShortClassName(classInfo);
65+
var shortClassName = getShortClassName(classInfo);
66+
return classInfo.isAnnotation() ? "@" + shortClassName : shortClassName;
5967
}
6068

6169
@Override
@@ -86,6 +94,11 @@ private AnnotationParameterValueList getParameterValues() {
8694

8795
record Method(MethodInfo methodInfo) implements Declaration {
8896

97+
@Override
98+
public String moduleName() {
99+
return classInfo().getModuleRef().getName();
100+
}
101+
89102
@Override
90103
public String packageName() {
91104
return classInfo().getPackageName();
@@ -98,14 +111,23 @@ public String fullName() {
98111

99112
@Override
100113
public String name() {
114+
if (classInfo().isAnnotation()) {
115+
return "@%s(%s=...)".formatted(getShortClassName(classInfo()), methodInfo.getName());
116+
}
117+
if (methodInfo.isConstructor()) {
118+
return "%s%s".formatted(getShortClassName(classInfo()), methodParameters());
119+
}
101120
return "%s.%s".formatted(getShortClassName(classInfo()), methodSignature());
102121
}
103122

104123
private String methodSignature() {
105-
var parameters = Arrays.stream(methodInfo.getParameterInfo()) //
124+
return methodInfo.getName() + methodParameters();
125+
}
126+
127+
private String methodParameters() {
128+
return Arrays.stream(methodInfo.getParameterInfo()) //
106129
.map(parameterInfo -> parameterInfo.getTypeSignatureOrTypeDescriptor().toStringWithSimpleNames()) //
107130
.collect(joining(", ", "(", ")"));
108-
return methodInfo.getName() + parameters;
109131
}
110132

111133
@Override
@@ -152,6 +174,6 @@ private static String getShortClassName(ClassInfo classInfo) {
152174
if (typeName.startsWith(packageName + '.')) {
153175
typeName = typeName.substring(packageName.length() + 1);
154176
}
155-
return typeName;
177+
return typeName.replace('$', '.');
156178
}
157179
}

documentation/src/tools/java/org/junit/api/tools/HtmlApiReportWriter.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
*/
1818
class HtmlApiReportWriter extends AbstractApiReportWriter {
1919

20-
private static final String HTML_HEADER_FORMAT = "\t<tr><th>%s</th><th>%s</th><th>%s</th></tr>%n";
21-
private static final String HTML_ROW_FORMAT = "\t<tr><td>%s</td><td>%s</td><td>%s</td></tr>%n";
20+
private static final String HTML_HEADER_FORMAT = "\t<tr><th>%s</th><th>%s</th></tr>%n";
21+
private static final String HTML_ROW_FORMAT = "\t<tr><td>%s</td><td>%s</td></tr>%n";
2222

2323
HtmlApiReportWriter(ApiReport apiReport) {
2424
super(apiReport);
@@ -34,6 +34,16 @@ protected String h2(String header) {
3434
return "<h2>" + header + "</h2>";
3535
}
3636

37+
@Override
38+
protected String h4(String header) {
39+
return "<h4>" + header + "</h4>";
40+
}
41+
42+
@Override
43+
protected String h5(String header) {
44+
return "<h5>" + header + "</h5>";
45+
}
46+
3747
@Override
3848
protected String code(String element) {
3949
return "<span class='code'>" + element + "</span>";
@@ -52,13 +62,12 @@ protected String paragraph(String element) {
5262
@Override
5363
protected void printDeclarationTableHeader(PrintWriter out) {
5464
out.println("<table>");
55-
out.printf(HTML_HEADER_FORMAT, "Package Name", "Name", "Since");
65+
out.printf(HTML_HEADER_FORMAT, "Name", "Since");
5666
}
5767

5868
@Override
5969
protected void printDeclarationTableRow(Declaration declaration, PrintWriter out) {
6070
out.printf(HTML_ROW_FORMAT, //
61-
code(declaration.packageName()), //
6271
code(declaration.name()) + " " + italic("(" + declaration.kind() + ")"), //
6372
code(declaration.since()) //
6473
);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy