From 9dccfdb5ecf69f1b76ce211d15804b98cc165b2c Mon Sep 17 00:00:00 2001 From: Burke Davison Date: Fri, 22 Sep 2023 14:06:01 -0400 Subject: [PATCH 01/15] chore: refactor to encapsulate package organization --- .../com/microsoft/build/ClassBuilder.java | 49 ++++++++++++++++--- .../com/microsoft/build/YmlFilesBuilder.java | 19 ++----- .../com/microsoft/lookup/PackageLookup.java | 4 ++ ... => ClassBuilderJoinTocTypeItemsTest.java} | 27 +--------- .../com/microsoft/build/ClassBuilderTest.java | 3 ++ 5 files changed, 54 insertions(+), 48 deletions(-) rename third_party/docfx-doclet-143274/src/test/java/com/microsoft/build/{YmlFilesBuilderTest.java => ClassBuilderJoinTocTypeItemsTest.java} (68%) diff --git a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java index 84e3d3eb..98708b55 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java @@ -18,8 +18,10 @@ import static com.microsoft.build.BuilderUtil.LANGS; import static com.microsoft.build.BuilderUtil.populateItemFields; +import com.google.common.annotations.VisibleForTesting; import com.microsoft.lookup.ClassItemsLookup; import com.microsoft.lookup.ClassLookup; +import com.microsoft.lookup.PackageLookup; import com.microsoft.model.MetadataFile; import com.microsoft.model.MetadataFileItem; import com.microsoft.model.TocItem; @@ -32,31 +34,50 @@ import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; import javax.lang.model.util.ElementFilter; class ClassBuilder { - private ElementUtil elementUtil; - private ClassLookup classLookup; - private ClassItemsLookup classItemsLookup; - private String outputPath; - private ReferenceBuilder referenceBuilder; + private final ElementUtil elementUtil; + private final ClassLookup classLookup; + private final ClassItemsLookup classItemsLookup; + private final String outputPath; + private final PackageLookup packageLookup; + private final ReferenceBuilder referenceBuilder; ClassBuilder( ElementUtil elementUtil, ClassLookup classLookup, ClassItemsLookup classItemsLookup, String outputPath, + PackageLookup packageLookup, ReferenceBuilder referenceBuilder) { this.elementUtil = elementUtil; this.classLookup = classLookup; this.classItemsLookup = classItemsLookup; this.outputPath = outputPath; + this.packageLookup = packageLookup; this.referenceBuilder = referenceBuilder; } + List buildFilesForPackage(PackageElement pkg, List classMetadataFiles) { + TocTypeMap typeMap = new TocTypeMap(); + if (packageLookup.isApiVersionPackage(pkg)) { + buildFilesForApiVersionPackage(pkg, typeMap, classMetadataFiles); + } else { + buildFilesForInnerClasses(pkg, typeMap, classMetadataFiles); + } + return joinTocTypeItems(typeMap); + } + + private void buildFilesForApiVersionPackage( + PackageElement pkg, TocTypeMap tocTypeMap, List classMetadataFiles) { + buildFilesForInnerClasses(pkg, tocTypeMap, classMetadataFiles); + } + void buildFilesForInnerClasses( - Element element, TocTypeMap tocTypeMap, List container) { + Element element, TocTypeMap tocTypeMap, List classMetadataFiles) { for (TypeElement classElement : elementUtil.extractSortedElements(element)) { String uid = classLookup.extractUid(classElement); String name = classLookup.extractTocName(classElement); @@ -73,8 +94,8 @@ void buildFilesForInnerClasses( tocTypeMap.get(ElementKind.CLASS.name()).add(new TocItem(uid, name, status)); } - container.add(buildClassYmlFile(classElement)); - buildFilesForInnerClasses(classElement, tocTypeMap, container); + classMetadataFiles.add(buildClassYmlFile(classElement)); + buildFilesForInnerClasses(classElement, tocTypeMap, classMetadataFiles); } } @@ -200,4 +221,16 @@ private List filterPrivateElements(List el .filter(element -> !Utils.isPrivateOrPackagePrivate(element)) .collect(Collectors.toList()); } + + @VisibleForTesting + static List joinTocTypeItems(TocTypeMap tocTypeMap) { + return tocTypeMap.getTitleList().stream() + .filter(kindTitle -> tocTypeMap.get(kindTitle.getElementKind()).size() > 0) + .flatMap( + kindTitle -> { + tocTypeMap.get(kindTitle.getElementKind()).add(0, new TocItem(kindTitle.getTitle())); + return tocTypeMap.get(kindTitle.getElementKind()).stream(); + }) + .collect(Collectors.toList()); + } } diff --git a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/YmlFilesBuilder.java b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/YmlFilesBuilder.java index fc87377f..0ea18ffe 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/YmlFilesBuilder.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/YmlFilesBuilder.java @@ -15,7 +15,6 @@ import com.microsoft.model.MetadataFileItem; import com.microsoft.model.TocFile; import com.microsoft.model.TocItem; -import com.microsoft.model.TocTypeMap; import com.microsoft.util.ElementUtil; import com.microsoft.util.FileUtil; import java.util.ArrayList; @@ -78,6 +77,7 @@ public YmlFilesBuilder( classLookup, new ClassItemsLookup(environment, elementUtil), outputPath, + packageLookup, referenceBuilder); } @@ -189,9 +189,9 @@ private TocItem buildPackage(PackageElement element) { packageMetadataFiles.add(packageBuilder.buildPackageMetadataFile(element)); // build classes/interfaces/enums/exceptions/annotations - TocTypeMap typeMap = new TocTypeMap(); - classBuilder.buildFilesForInnerClasses(element, typeMap, classMetadataFiles); - packageTocItem.getItems().addAll(joinTocTypeItems(typeMap)); + packageTocItem + .getItems() + .addAll(classBuilder.buildFilesForPackage(element, classMetadataFiles)); // build stubs packageLookup @@ -201,15 +201,4 @@ private TocItem buildPackage(PackageElement element) { return packageTocItem; } } - - List joinTocTypeItems(TocTypeMap tocTypeMap) { - return tocTypeMap.getTitleList().stream() - .filter(kindTitle -> tocTypeMap.get(kindTitle.getElementKind()).size() > 0) - .flatMap( - kindTitle -> { - tocTypeMap.get(kindTitle.getElementKind()).add(0, new TocItem(kindTitle.getTitle())); - return tocTypeMap.get(kindTitle.getElementKind()).stream(); - }) - .collect(Collectors.toList()); - } } diff --git a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/lookup/PackageLookup.java b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/lookup/PackageLookup.java index 3a78a656..27345c73 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/lookup/PackageLookup.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/lookup/PackageLookup.java @@ -110,6 +110,10 @@ public Optional extractApiVersion(String name) { return ApiVersion.parse(getLeafPackage(name)); } + public boolean isApiVersionPackage(PackageElement pkg) { + return extractApiVersion(pkg).isPresent(); + } + public enum PackageGroup { VISIBLE, OLDER_AND_PRERELEASE diff --git a/third_party/docfx-doclet-143274/src/test/java/com/microsoft/build/YmlFilesBuilderTest.java b/third_party/docfx-doclet-143274/src/test/java/com/microsoft/build/ClassBuilderJoinTocTypeItemsTest.java similarity index 68% rename from third_party/docfx-doclet-143274/src/test/java/com/microsoft/build/YmlFilesBuilderTest.java rename to third_party/docfx-doclet-143274/src/test/java/com/microsoft/build/ClassBuilderJoinTocTypeItemsTest.java index 1845417f..61b63d09 100644 --- a/third_party/docfx-doclet-143274/src/test/java/com/microsoft/build/YmlFilesBuilderTest.java +++ b/third_party/docfx-doclet-143274/src/test/java/com/microsoft/build/ClassBuilderJoinTocTypeItemsTest.java @@ -6,35 +6,12 @@ import com.microsoft.model.TocTypeMap; import java.util.List; import javax.lang.model.element.ElementKind; -import jdk.javadoc.doclet.DocletEnvironment; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) -public class YmlFilesBuilderTest { - - private YmlFilesBuilder ymlFilesBuilder; - private DocletEnvironment environment; - - @Before - public void setup() { - environment = Mockito.mock(DocletEnvironment.class); - ymlFilesBuilder = - new YmlFilesBuilder( - environment, - "./target", - new String[] {}, - new String[] {}, - "google-cloud-product", - false, - false, - "0.18.0", - "26.19.0", - "./src/test/java/com/microsoft/samples/.repo-metadata.json"); - } +public class ClassBuilderJoinTocTypeItemsTest { @Test public void joinTocTypeItems() { @@ -51,7 +28,7 @@ public void joinTocTypeItems() { typeMap.get(ElementKind.ANNOTATION_TYPE.name()).add(annotationToc); typeMap.get("EXCEPTION").add(exceptionToc); - List tocItems = ymlFilesBuilder.joinTocTypeItems(typeMap); + List tocItems = ClassBuilder.joinTocTypeItems(typeMap); assertEquals("Interfaces", tocItems.get(0).getHeading()); assertEquals(interfaceToc, tocItems.get(1)); diff --git a/third_party/docfx-doclet-143274/src/test/java/com/microsoft/build/ClassBuilderTest.java b/third_party/docfx-doclet-143274/src/test/java/com/microsoft/build/ClassBuilderTest.java index 9b8cbe97..d3945f64 100644 --- a/third_party/docfx-doclet-143274/src/test/java/com/microsoft/build/ClassBuilderTest.java +++ b/third_party/docfx-doclet-143274/src/test/java/com/microsoft/build/ClassBuilderTest.java @@ -21,6 +21,7 @@ import com.google.testing.compile.CompilationRule; import com.microsoft.lookup.ClassItemsLookup; import com.microsoft.lookup.ClassLookup; +import com.microsoft.lookup.PackageLookup; import com.microsoft.model.MetadataFile; import com.microsoft.model.MetadataFileItem; import com.microsoft.util.ElementUtil; @@ -49,12 +50,14 @@ public void setup() { docTrees = Mockito.mock(DocTrees.class); ElementUtil elementUtil = new ElementUtil(new String[0], new String[0]); ClassLookup classLookup = new ClassLookup(environment, elementUtil); + PackageLookup packageLookup = new PackageLookup(environment); classBuilder = new ClassBuilder( elementUtil, classLookup, new ClassItemsLookup(environment, elementUtil), "./target", + packageLookup, new ReferenceBuilder(environment, classLookup, elementUtil)); } From 9a81db5970ca2288f49e77ae120770f85f41320b Mon Sep 17 00:00:00 2001 From: Burke Davison Date: Thu, 28 Sep 2023 14:47:16 -0400 Subject: [PATCH 02/15] feat: organize package contents into collapsed categories --- .../com/microsoft/build/ClassBuilder.java | 56 ++++++--- .../microsoft/model/ApiVersionPackageToc.java | 111 ++++++++++++++++++ .../java/com/microsoft/model/TocTypeMap.java | 12 ++ ...TypeItemsTest.java => TocTypeMapTest.java} | 6 +- .../microsoft/doclet/DocletRunnerTest.java | 4 +- .../expected-generated-files/toc.yml | 24 ++-- 6 files changed, 181 insertions(+), 32 deletions(-) create mode 100644 third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java rename third_party/docfx-doclet-143274/src/test/java/com/microsoft/build/{ClassBuilderJoinTocTypeItemsTest.java => TocTypeMapTest.java} (91%) diff --git a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java index 98708b55..6ab83b83 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java @@ -18,10 +18,10 @@ import static com.microsoft.build.BuilderUtil.LANGS; import static com.microsoft.build.BuilderUtil.populateItemFields; -import com.google.common.annotations.VisibleForTesting; import com.microsoft.lookup.ClassItemsLookup; import com.microsoft.lookup.ClassLookup; import com.microsoft.lookup.PackageLookup; +import com.microsoft.model.ApiVersionPackageToc; import com.microsoft.model.MetadataFile; import com.microsoft.model.MetadataFileItem; import com.microsoft.model.TocItem; @@ -62,18 +62,50 @@ class ClassBuilder { } List buildFilesForPackage(PackageElement pkg, List classMetadataFiles) { - TocTypeMap typeMap = new TocTypeMap(); if (packageLookup.isApiVersionPackage(pkg)) { - buildFilesForApiVersionPackage(pkg, typeMap, classMetadataFiles); + ApiVersionPackageToc apiVersionPackageToc = new ApiVersionPackageToc(); + buildFilesForApiVersionPackage(pkg, apiVersionPackageToc, classMetadataFiles); + return apiVersionPackageToc.toList(); } else { + TocTypeMap typeMap = new TocTypeMap(); buildFilesForInnerClasses(pkg, typeMap, classMetadataFiles); + return typeMap.toList(); } - return joinTocTypeItems(typeMap); } private void buildFilesForApiVersionPackage( - PackageElement pkg, TocTypeMap tocTypeMap, List classMetadataFiles) { - buildFilesForInnerClasses(pkg, tocTypeMap, classMetadataFiles); + Element element, + ApiVersionPackageToc apiVersionPackageToc, + List classMetadataFiles) { + for (TypeElement classElement : elementUtil.extractSortedElements(element)) { + String uid = classLookup.extractUid(classElement); + String name = classLookup.extractTocName(classElement); + String status = classLookup.extractStatus(classElement); + TocItem tocItem = new TocItem(uid, name, status); + + if (name.endsWith("Client")) { + apiVersionPackageToc.addClient(tocItem); + } else if (name.endsWith("Response") || name.endsWith("Request")) { + apiVersionPackageToc.addRequestOrResponse(tocItem); + } else if (name.endsWith("Settings")) { + apiVersionPackageToc.addSettings(tocItem); + } else if (name.endsWith("Builder")) { + apiVersionPackageToc.addBuilder(tocItem); + } else if (classElement.getKind() == ElementKind.ENUM) { + apiVersionPackageToc.addEnum(tocItem); + } else if (name.endsWith("Exception")) { + apiVersionPackageToc.addException(tocItem); + } else if (String.valueOf(classElement.getSuperclass()).contains("GeneratedMessage")) { + apiVersionPackageToc.addMessage(tocItem); + } else if (classElement.getKind() == ElementKind.INTERFACE) { + apiVersionPackageToc.addInterface(tocItem); + } else { + apiVersionPackageToc.addUncategorized(tocItem); + } + + classMetadataFiles.add(buildClassYmlFile(classElement)); + buildFilesForApiVersionPackage(classElement, apiVersionPackageToc, classMetadataFiles); + } } void buildFilesForInnerClasses( @@ -221,16 +253,4 @@ private List filterPrivateElements(List el .filter(element -> !Utils.isPrivateOrPackagePrivate(element)) .collect(Collectors.toList()); } - - @VisibleForTesting - static List joinTocTypeItems(TocTypeMap tocTypeMap) { - return tocTypeMap.getTitleList().stream() - .filter(kindTitle -> tocTypeMap.get(kindTitle.getElementKind()).size() > 0) - .flatMap( - kindTitle -> { - tocTypeMap.get(kindTitle.getElementKind()).add(0, new TocItem(kindTitle.getTitle())); - return tocTypeMap.get(kindTitle.getElementKind()).stream(); - }) - .collect(Collectors.toList()); - } } diff --git a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java new file mode 100644 index 00000000..187ec2c7 --- /dev/null +++ b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java @@ -0,0 +1,111 @@ +package com.microsoft.model; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +public class ApiVersionPackageToc { + static final String CLIENTS = "Clients"; + static final String REQUESTS_AND_RESPONSES = "Requests and responses"; + static final String SETTINGS = "Settings"; + static final String ALL_OTHERS = "All other classes and interfaces"; + static final String BUILDERS = "Builders"; + static final String ENUMS = "Enums"; + static final String INTERFACES = "Interfaces"; + static final String MESSAGES = "Messages"; + static final String EXCEPTIONS = "Exceptions"; + + private final List clients = new ArrayList<>(); + private final List requestsAndResponses = new ArrayList<>(); + private final List settings = new ArrayList<>(); + private final List builders = new ArrayList<>(); + private final List enums = new ArrayList<>(); + private final List exceptions = new ArrayList<>(); + private final List interfaces = new ArrayList<>(); + private final List messages = new ArrayList<>(); + private final List uncategorized = new ArrayList<>(); + + public void addClient(TocItem tocItem) { + clients.add(tocItem); + } + + public void addRequestOrResponse(TocItem tocItem) { + requestsAndResponses.add(tocItem); + } + + public void addSettings(TocItem tocItem) { + settings.add(tocItem); + } + + public void addBuilder(TocItem tocItem) { + builders.add(tocItem); + } + + public void addEnum(TocItem tocItem) { + enums.add(tocItem); + } + + public void addException(TocItem tocItem) { + exceptions.add(tocItem); + } + + public void addInterface(TocItem tocItem) { + interfaces.add(tocItem); + } + + public void addMessage(TocItem tocItem) { + messages.add(tocItem); + } + + public void addUncategorized(TocItem tocItem) { + uncategorized.add(tocItem); + } + + /** Build a list of TocItems for inclusion in the library's table of contents */ + public List toList() { + List toc = new ArrayList<>(); + if (!clients.isEmpty()) { + toc.add(createCategory(CLIENTS, clients)); + } + if (!requestsAndResponses.isEmpty()) { + toc.add(createCategory(REQUESTS_AND_RESPONSES, requestsAndResponses)); + } + if (!settings.isEmpty()) { + toc.add(createCategory(SETTINGS, settings)); + } + if (!builders.isEmpty() + || !enums.isEmpty() + || !exceptions.isEmpty() + || !interfaces.isEmpty() + || !messages.isEmpty() + || !uncategorized.isEmpty()) { + TocItem allOthers = new TocItem(ALL_OTHERS, ALL_OTHERS, null); + if (!builders.isEmpty()) { + allOthers.getItems().add(createCategory(BUILDERS, builders)); + } + if (!enums.isEmpty()) { + allOthers.getItems().add(createCategory(ENUMS, enums)); + } + if (!exceptions.isEmpty()) { + allOthers.getItems().add(createCategory(EXCEPTIONS, exceptions)); + } + if (!interfaces.isEmpty()) { + allOthers.getItems().add(createCategory(INTERFACES, interfaces)); + } + if (!messages.isEmpty()) { + allOthers.getItems().add(createCategory(MESSAGES, messages)); + } + uncategorized.sort(Comparator.comparing(TocItem::getName)); + allOthers.getItems().addAll(uncategorized); + toc.add(allOthers); + } + return toc; + } + + private TocItem createCategory(String name, List items) { + TocItem category = new TocItem(name, name, null); + items.sort(Comparator.comparing(TocItem::getName)); + category.getItems().addAll(items); + return category; + } +} diff --git a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/TocTypeMap.java b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/TocTypeMap.java index 7e8b9869..55cacb17 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/TocTypeMap.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/TocTypeMap.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.stream.Collectors; import javax.lang.model.element.ElementKind; public class TocTypeMap extends HashMap> { @@ -38,4 +39,15 @@ public List getTitleList() { new KindTitle(ElementKind.ANNOTATION_TYPE.name(), "Annotation Types"), new KindTitle("EXCEPTION", "Exceptions")); } + + public List toList() { + return getTitleList().stream() + .filter(kindTitle -> get(kindTitle.getElementKind()).size() > 0) + .flatMap( + kindTitle -> { + get(kindTitle.getElementKind()).add(0, new TocItem(kindTitle.getTitle())); + return get(kindTitle.getElementKind()).stream(); + }) + .collect(Collectors.toList()); + } } diff --git a/third_party/docfx-doclet-143274/src/test/java/com/microsoft/build/ClassBuilderJoinTocTypeItemsTest.java b/third_party/docfx-doclet-143274/src/test/java/com/microsoft/build/TocTypeMapTest.java similarity index 91% rename from third_party/docfx-doclet-143274/src/test/java/com/microsoft/build/ClassBuilderJoinTocTypeItemsTest.java rename to third_party/docfx-doclet-143274/src/test/java/com/microsoft/build/TocTypeMapTest.java index 61b63d09..0f58ae07 100644 --- a/third_party/docfx-doclet-143274/src/test/java/com/microsoft/build/ClassBuilderJoinTocTypeItemsTest.java +++ b/third_party/docfx-doclet-143274/src/test/java/com/microsoft/build/TocTypeMapTest.java @@ -11,10 +11,10 @@ import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) -public class ClassBuilderJoinTocTypeItemsTest { +public class TocTypeMapTest { @Test - public void joinTocTypeItems() { + public void testToList() { TocTypeMap typeMap = new TocTypeMap(); TocItem classToc = new TocItem("uid1", "name1"); TocItem interfaceToc = new TocItem("uid2", "name2"); @@ -28,7 +28,7 @@ public void joinTocTypeItems() { typeMap.get(ElementKind.ANNOTATION_TYPE.name()).add(annotationToc); typeMap.get("EXCEPTION").add(exceptionToc); - List tocItems = ClassBuilder.joinTocTypeItems(typeMap); + List tocItems = typeMap.toList(); assertEquals("Interfaces", tocItems.get(0).getHeading()); assertEquals(interfaceToc, tocItems.get(1)); diff --git a/third_party/docfx-doclet-143274/src/test/java/com/microsoft/doclet/DocletRunnerTest.java b/third_party/docfx-doclet-143274/src/test/java/com/microsoft/doclet/DocletRunnerTest.java index f3d20cd6..9bc72d5c 100644 --- a/third_party/docfx-doclet-143274/src/test/java/com/microsoft/doclet/DocletRunnerTest.java +++ b/third_party/docfx-doclet-143274/src/test/java/com/microsoft/doclet/DocletRunnerTest.java @@ -30,6 +30,8 @@ public class DocletRunnerTest { private final PrintStream originalOut = System.out; private final PrintStream originalErr = System.err; + @Rule public final EnvironmentVariables environmentVariables = new EnvironmentVariables(); + @Before public void cleanup() throws IOException { FileUtilTest.deleteDirectory(OUTPUT_DIR); @@ -67,8 +69,6 @@ public void testFilesGenerationWhenTargetFileDoesNotExist() { } } - @Rule public final EnvironmentVariables environmentVariables = new EnvironmentVariables(); - @Test public void testFilesGeneration() throws IOException { environmentVariables.set("artifactVersion", "0.18.0"); diff --git a/third_party/docfx-doclet-143274/src/test/resources/expected-generated-files/toc.yml b/third_party/docfx-doclet-143274/src/test/resources/expected-generated-files/toc.yml index 6aa271c4..c6e70146 100644 --- a/third_party/docfx-doclet-143274/src/test/resources/expected-generated-files/toc.yml +++ b/third_party/docfx-doclet-143274/src/test/resources/expected-generated-files/toc.yml @@ -113,9 +113,11 @@ items: - uid: "com.microsoft.samples.google.v1" name: "Package summary" - - heading: "Classes" - - uid: "com.microsoft.samples.google.v1.SpeechClient" - name: "SpeechClient" + - uid: "Clients" + name: "Clients" + items: + - uid: "com.microsoft.samples.google.v1.SpeechClient" + name: "SpeechClient" - uid: "com.microsoft.samples.google.v1.stub" name: "com.microsoft.samples.google.v1.stub" items: @@ -170,15 +172,19 @@ items: - uid: "com.microsoft.samples.google.v1beta" name: "Package summary" - - heading: "Classes" - - uid: "com.microsoft.samples.google.v1beta.SpeechClient" - name: "SpeechClient" + - uid: "Clients" + name: "Clients" + items: + - uid: "com.microsoft.samples.google.v1beta.SpeechClient" + name: "SpeechClient" - uid: "com.microsoft.samples.google.v1p1alpha" name: "com.microsoft.samples.google.v1p1alpha" status: "alpha" items: - uid: "com.microsoft.samples.google.v1p1alpha" name: "Package summary" - - heading: "Classes" - - uid: "com.microsoft.samples.google.v1p1alpha.SpeechClient" - name: "SpeechClient" + - uid: "Clients" + name: "Clients" + items: + - uid: "com.microsoft.samples.google.v1p1alpha.SpeechClient" + name: "SpeechClient" From 11bfce24346df4a37a112f36f0eb62b35e80440e Mon Sep 17 00:00:00 2001 From: Burke Davison Date: Thu, 28 Sep 2023 14:58:00 -0400 Subject: [PATCH 03/15] fix: sort by package qualified name --- .../src/main/java/com/microsoft/lookup/PackageLookup.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/lookup/PackageLookup.java b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/lookup/PackageLookup.java index 27345c73..d9394854 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/lookup/PackageLookup.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/lookup/PackageLookup.java @@ -94,7 +94,7 @@ public List findStubPackages( String expectedStubPackageBase = pkg.getQualifiedName() + ".stub"; return packages.stream() .filter(p -> String.valueOf(p.getQualifiedName()).startsWith(expectedStubPackageBase)) - .sorted() + .sorted(Comparator.comparing(p -> String.valueOf(p.getQualifiedName()))) .collect(Collectors.toList()); } From d80567e1ddb2474ef685030ce52039fb86650fcc Mon Sep 17 00:00:00 2001 From: Burke Davison Date: Thu, 28 Sep 2023 15:06:21 -0400 Subject: [PATCH 04/15] fix: use path to find repo-metadata file, or fail with improved message --- .../main/java/com/google/docfx/doclet/RepoMetadata.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/RepoMetadata.java b/third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/RepoMetadata.java index 9ddbdee1..2b9311de 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/RepoMetadata.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/RepoMetadata.java @@ -6,6 +6,8 @@ import com.google.gson.annotations.SerializedName; import java.io.FileReader; import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Objects; public class RepoMetadata { @@ -140,10 +142,11 @@ public String getMavenLink() { public RepoMetadata parseRepoMetadata(String fileName) { Gson gson = new Gson(); - try (FileReader reader = new FileReader(fileName)) { + Path path = Paths.get(fileName); + try (FileReader reader = new FileReader(path.toFile())) { return gson.fromJson(reader, RepoMetadata.class); } catch (IOException e) { - throw new RuntimeException(".repo-metadata.json is not found", e); + throw new RuntimeException(".repo-metadata.json is not found @ " + path.toAbsolutePath(), e); } } } From 98166a284db4b6a0abe7108d8aab7f5041259c72 Mon Sep 17 00:00:00 2001 From: Burke Davison Date: Fri, 29 Sep 2023 10:17:11 -0400 Subject: [PATCH 05/15] fix: improve repo-metadata error messages --- .../src/main/java/com/google/docfx/doclet/RepoMetadata.java | 3 ++- .../src/main/java/com/microsoft/doclet/DocFxDoclet.java | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/RepoMetadata.java b/third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/RepoMetadata.java index 2b9311de..9629d464 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/RepoMetadata.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/RepoMetadata.java @@ -2,6 +2,7 @@ // This parses .repo-metadata.json files to create a new library overview +import com.google.common.base.Preconditions; import com.google.gson.Gson; import com.google.gson.annotations.SerializedName; import java.io.FileReader; @@ -146,7 +147,7 @@ public RepoMetadata parseRepoMetadata(String fileName) { try (FileReader reader = new FileReader(path.toFile())) { return gson.fromJson(reader, RepoMetadata.class); } catch (IOException e) { - throw new RuntimeException(".repo-metadata.json is not found @ " + path.toAbsolutePath(), e); + throw new RuntimeException(".repo-metadata.json is not found @ " + path.toAbsolutePath().normalize() + ". Modify environment variable 'repoMetadataFilePath'", e); } } } diff --git a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/doclet/DocFxDoclet.java b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/doclet/DocFxDoclet.java index a648496b..045f8810 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/doclet/DocFxDoclet.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/doclet/DocFxDoclet.java @@ -24,6 +24,7 @@ public boolean run(DocletEnvironment environment) { String artifactVersion = System.getenv("artifactVersion"); String librariesBomVersion = System.getenv("librariesBomVersion"); String repoMetadataFilePath = System.getenv("repoMetadataFilePath"); + Objects.requireNonNull(repoMetadataFilePath, "Environment variable 'repoMetadataFilePath' must not be null."); reporter.print(Kind.NOTE, "Environment variable artifactVersion: " + artifactVersion); reporter.print(Kind.NOTE, "Environment variable librariesBomVersion: " + librariesBomVersion); reporter.print(Kind.NOTE, "Environment variable repoMetadataFilePath: " + repoMetadataFilePath); From 55c98efec4c876fa15ac768fa6220ef8f711d352 Mon Sep 17 00:00:00 2001 From: Burke Davison Date: Fri, 29 Sep 2023 10:54:26 -0400 Subject: [PATCH 06/15] chore: add additional categories --- .../com/microsoft/build/ClassBuilder.java | 26 ++++++++++++++++--- .../microsoft/model/ApiVersionPackageToc.java | 26 +++++++++++++++++-- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java index 6ab83b83..f271414b 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java @@ -39,6 +39,7 @@ import javax.lang.model.util.ElementFilter; class ClassBuilder { + private final ElementUtil elementUtil; private final ClassLookup classLookup; private final ClassItemsLookup classItemsLookup; @@ -83,7 +84,9 @@ private void buildFilesForApiVersionPackage( String status = classLookup.extractStatus(classElement); TocItem tocItem = new TocItem(uid, name, status); - if (name.endsWith("Client")) { + if (classElement.getKind() == ElementKind.INTERFACE) { + apiVersionPackageToc.addInterface(tocItem); + } else if (name.endsWith("Client")) { apiVersionPackageToc.addClient(tocItem); } else if (name.endsWith("Response") || name.endsWith("Request")) { apiVersionPackageToc.addRequestOrResponse(tocItem); @@ -95,10 +98,12 @@ private void buildFilesForApiVersionPackage( apiVersionPackageToc.addEnum(tocItem); } else if (name.endsWith("Exception")) { apiVersionPackageToc.addException(tocItem); - } else if (String.valueOf(classElement.getSuperclass()).contains("GeneratedMessage")) { + } else if (isGeneratedMessage(classElement)) { apiVersionPackageToc.addMessage(tocItem); - } else if (classElement.getKind() == ElementKind.INTERFACE) { - apiVersionPackageToc.addInterface(tocItem); + } else if (isPagingClass(classElement)) { + apiVersionPackageToc.addPaging(tocItem); + } else if (isResourceName(classElement)) { + apiVersionPackageToc.addResourceName(tocItem); } else { apiVersionPackageToc.addUncategorized(tocItem); } @@ -108,6 +113,19 @@ private void buildFilesForApiVersionPackage( } } + boolean isResourceName(TypeElement classElement) { + return classElement.getInterfaces().stream().map(String::valueOf) + .anyMatch(i -> i.contains("ResourceName")); + } + + boolean isGeneratedMessage(TypeElement classElement) { + return String.valueOf(classElement.getSuperclass()).contains("GeneratedMessage"); + } + + boolean isPagingClass(TypeElement classElement) { + return String.valueOf(classElement.getSuperclass()).contains(".paging."); + } + void buildFilesForInnerClasses( Element element, TocTypeMap tocTypeMap, List classMetadataFiles) { for (TypeElement classElement : elementUtil.extractSortedElements(element)) { diff --git a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java index 187ec2c7..cda8b5e0 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java @@ -14,6 +14,9 @@ public class ApiVersionPackageToc { static final String INTERFACES = "Interfaces"; static final String MESSAGES = "Messages"; static final String EXCEPTIONS = "Exceptions"; + static final String PAGING = "Paging"; + static final String RESOURCE_NAMES = "Resource Names"; + static final String UNCATEGORIZED = "Other"; private final List clients = new ArrayList<>(); private final List requestsAndResponses = new ArrayList<>(); @@ -23,6 +26,8 @@ public class ApiVersionPackageToc { private final List exceptions = new ArrayList<>(); private final List interfaces = new ArrayList<>(); private final List messages = new ArrayList<>(); + private final List paging = new ArrayList<>(); + private final List resourceNames = new ArrayList<>(); private final List uncategorized = new ArrayList<>(); public void addClient(TocItem tocItem) { @@ -61,6 +66,14 @@ public void addUncategorized(TocItem tocItem) { uncategorized.add(tocItem); } + public void addPaging(TocItem tocItem) { + paging.add(tocItem); + } + + public void addResourceName(TocItem tocItem) { + resourceNames.add(tocItem); + } + /** Build a list of TocItems for inclusion in the library's table of contents */ public List toList() { List toc = new ArrayList<>(); @@ -78,6 +91,8 @@ public List toList() { || !exceptions.isEmpty() || !interfaces.isEmpty() || !messages.isEmpty() + || !paging.isEmpty() + || !resourceNames.isEmpty() || !uncategorized.isEmpty()) { TocItem allOthers = new TocItem(ALL_OTHERS, ALL_OTHERS, null); if (!builders.isEmpty()) { @@ -95,8 +110,15 @@ public List toList() { if (!messages.isEmpty()) { allOthers.getItems().add(createCategory(MESSAGES, messages)); } - uncategorized.sort(Comparator.comparing(TocItem::getName)); - allOthers.getItems().addAll(uncategorized); + if (!paging.isEmpty()) { + allOthers.getItems().add(createCategory(PAGING, paging)); + } + if (!resourceNames.isEmpty()) { + allOthers.getItems().add(createCategory(RESOURCE_NAMES, resourceNames)); + } + if (!uncategorized.isEmpty()) { + allOthers.getItems().add(createCategory(UNCATEGORIZED, uncategorized)); + } toc.add(allOthers); } return toc; From 449a583b74d2dcf0ffe95dc78a94360d8fa078fb Mon Sep 17 00:00:00 2001 From: Burke Davison Date: Fri, 29 Sep 2023 13:32:07 -0400 Subject: [PATCH 07/15] chore: do not organize packages without a client --- .../com/google/docfx/doclet/RepoMetadata.java | 4 +-- .../com/microsoft/build/ClassBuilder.java | 27 ++++++++++++++----- .../com/microsoft/doclet/DocFxDoclet.java | 3 ++- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/RepoMetadata.java b/third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/RepoMetadata.java index 9629d464..a4ed13e0 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/RepoMetadata.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/RepoMetadata.java @@ -2,7 +2,6 @@ // This parses .repo-metadata.json files to create a new library overview -import com.google.common.base.Preconditions; import com.google.gson.Gson; import com.google.gson.annotations.SerializedName; import java.io.FileReader; @@ -147,7 +146,8 @@ public RepoMetadata parseRepoMetadata(String fileName) { try (FileReader reader = new FileReader(path.toFile())) { return gson.fromJson(reader, RepoMetadata.class); } catch (IOException e) { - throw new RuntimeException(".repo-metadata.json is not found @ " + path.toAbsolutePath().normalize() + ". Modify environment variable 'repoMetadataFilePath'", e); + throw new RuntimeException( + ".repo-metadata.json is not found @ " + path.toAbsolutePath().normalize(), e); } } } diff --git a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java index f271414b..9bf2e371 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java @@ -63,13 +63,16 @@ class ClassBuilder { } List buildFilesForPackage(PackageElement pkg, List classMetadataFiles) { - if (packageLookup.isApiVersionPackage(pkg)) { + if (packageLookup.isApiVersionPackage(pkg) && containsAtLeastOneClient(pkg)) { + // API Version package organization is a nested list organized by GAPIC concepts ApiVersionPackageToc apiVersionPackageToc = new ApiVersionPackageToc(); buildFilesForApiVersionPackage(pkg, apiVersionPackageToc, classMetadataFiles); return apiVersionPackageToc.toList(); + } else { + // Standard package organization is a flat list organized by Java type TocTypeMap typeMap = new TocTypeMap(); - buildFilesForInnerClasses(pkg, typeMap, classMetadataFiles); + buildFilesForStandardPackage(pkg, typeMap, classMetadataFiles); return typeMap.toList(); } } @@ -84,9 +87,11 @@ private void buildFilesForApiVersionPackage( String status = classLookup.extractStatus(classElement); TocItem tocItem = new TocItem(uid, name, status); + // The order of these checks matter! + // Ex: a paging response class would change its category if "isPagingClass" is checked first. if (classElement.getKind() == ElementKind.INTERFACE) { apiVersionPackageToc.addInterface(tocItem); - } else if (name.endsWith("Client")) { + } else if (isClient(classElement)) { apiVersionPackageToc.addClient(tocItem); } else if (name.endsWith("Response") || name.endsWith("Request")) { apiVersionPackageToc.addRequestOrResponse(tocItem); @@ -113,9 +118,17 @@ private void buildFilesForApiVersionPackage( } } + boolean containsAtLeastOneClient(PackageElement pkg) { + return elementUtil.extractSortedElements(pkg).stream().anyMatch(this::isClient); + } + + boolean isClient(TypeElement classElement) { + return classLookup.extractTocName(classElement).endsWith("Client"); + } + boolean isResourceName(TypeElement classElement) { - return classElement.getInterfaces().stream().map(String::valueOf) - .anyMatch(i -> i.contains("ResourceName")); + return classElement.getInterfaces().stream() + .anyMatch(i -> String.valueOf(i).contains("ResourceName")); } boolean isGeneratedMessage(TypeElement classElement) { @@ -126,7 +139,7 @@ boolean isPagingClass(TypeElement classElement) { return String.valueOf(classElement.getSuperclass()).contains(".paging."); } - void buildFilesForInnerClasses( + void buildFilesForStandardPackage( Element element, TocTypeMap tocTypeMap, List classMetadataFiles) { for (TypeElement classElement : elementUtil.extractSortedElements(element)) { String uid = classLookup.extractUid(classElement); @@ -145,7 +158,7 @@ void buildFilesForInnerClasses( } classMetadataFiles.add(buildClassYmlFile(classElement)); - buildFilesForInnerClasses(classElement, tocTypeMap, classMetadataFiles); + buildFilesForStandardPackage(classElement, tocTypeMap, classMetadataFiles); } } diff --git a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/doclet/DocFxDoclet.java b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/doclet/DocFxDoclet.java index 045f8810..e4c3051e 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/doclet/DocFxDoclet.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/doclet/DocFxDoclet.java @@ -24,7 +24,8 @@ public boolean run(DocletEnvironment environment) { String artifactVersion = System.getenv("artifactVersion"); String librariesBomVersion = System.getenv("librariesBomVersion"); String repoMetadataFilePath = System.getenv("repoMetadataFilePath"); - Objects.requireNonNull(repoMetadataFilePath, "Environment variable 'repoMetadataFilePath' must not be null."); + Objects.requireNonNull( + repoMetadataFilePath, "Environment variable 'repoMetadataFilePath' must not be null."); reporter.print(Kind.NOTE, "Environment variable artifactVersion: " + artifactVersion); reporter.print(Kind.NOTE, "Environment variable librariesBomVersion: " + librariesBomVersion); reporter.print(Kind.NOTE, "Environment variable repoMetadataFilePath: " + repoMetadataFilePath); From f41aa542fc17f385b48e374c7911702ef6d3a6e6 Mon Sep 17 00:00:00 2001 From: Burke Davison Date: Fri, 29 Sep 2023 14:01:34 -0400 Subject: [PATCH 08/15] fix: sentence casing for category titles --- .../java/com/microsoft/model/ApiVersionPackageToc.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java index cda8b5e0..c4057483 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java @@ -15,7 +15,7 @@ public class ApiVersionPackageToc { static final String MESSAGES = "Messages"; static final String EXCEPTIONS = "Exceptions"; static final String PAGING = "Paging"; - static final String RESOURCE_NAMES = "Resource Names"; + static final String RESOURCE_NAMES = "Resource names"; static final String UNCATEGORIZED = "Other"; private final List clients = new ArrayList<>(); @@ -104,9 +104,6 @@ public List toList() { if (!exceptions.isEmpty()) { allOthers.getItems().add(createCategory(EXCEPTIONS, exceptions)); } - if (!interfaces.isEmpty()) { - allOthers.getItems().add(createCategory(INTERFACES, interfaces)); - } if (!messages.isEmpty()) { allOthers.getItems().add(createCategory(MESSAGES, messages)); } @@ -116,6 +113,9 @@ public List toList() { if (!resourceNames.isEmpty()) { allOthers.getItems().add(createCategory(RESOURCE_NAMES, resourceNames)); } + if (!interfaces.isEmpty()) { + allOthers.getItems().add(createCategory(INTERFACES, interfaces)); + } if (!uncategorized.isEmpty()) { allOthers.getItems().add(createCategory(UNCATEGORIZED, uncategorized)); } From 672f8ff9038e395e76edbb638e3d48a2d06e9f59 Mon Sep 17 00:00:00 2001 From: Burke Davison Date: Mon, 2 Oct 2023 11:31:49 -0400 Subject: [PATCH 09/15] chore: refactor ApiVersionPackageToc for better testing --- .../microsoft/model/ApiVersionPackageToc.java | 107 +++++++----------- .../model/ApiVersionPackageTocTest.java | 72 ++++++++++++ 2 files changed, 116 insertions(+), 63 deletions(-) create mode 100644 third_party/docfx-doclet-143274/src/test/java/com/microsoft/model/ApiVersionPackageTocTest.java diff --git a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java index c4057483..fd09ca4b 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.Comparator; +import java.util.LinkedHashMap; import java.util.List; public class ApiVersionPackageToc { @@ -18,109 +19,89 @@ public class ApiVersionPackageToc { static final String RESOURCE_NAMES = "Resource names"; static final String UNCATEGORIZED = "Other"; - private final List clients = new ArrayList<>(); - private final List requestsAndResponses = new ArrayList<>(); - private final List settings = new ArrayList<>(); - private final List builders = new ArrayList<>(); - private final List enums = new ArrayList<>(); - private final List exceptions = new ArrayList<>(); - private final List interfaces = new ArrayList<>(); - private final List messages = new ArrayList<>(); - private final List paging = new ArrayList<>(); - private final List resourceNames = new ArrayList<>(); - private final List uncategorized = new ArrayList<>(); - + private final LinkedHashMap> visibleCategories = new LinkedHashMap<>(); + private final LinkedHashMap> hiddenCategories = new LinkedHashMap<>(); + + public ApiVersionPackageToc() { + // Order here determines final organization order. + visibleCategories.put(CLIENTS, new ArrayList<>()); + visibleCategories.put(REQUESTS_AND_RESPONSES, new ArrayList<>()); + visibleCategories.put(SETTINGS, new ArrayList<>()); + + hiddenCategories.put(BUILDERS, new ArrayList<>()); + hiddenCategories.put(ENUMS, new ArrayList<>()); + hiddenCategories.put(EXCEPTIONS, new ArrayList<>()); + hiddenCategories.put(MESSAGES, new ArrayList<>()); + hiddenCategories.put(PAGING, new ArrayList<>()); + hiddenCategories.put(RESOURCE_NAMES, new ArrayList<>()); + hiddenCategories.put(INTERFACES, new ArrayList<>()); + hiddenCategories.put(UNCATEGORIZED, new ArrayList<>()); + } + public void addClient(TocItem tocItem) { - clients.add(tocItem); + visibleCategories.get(CLIENTS).add(tocItem); } public void addRequestOrResponse(TocItem tocItem) { - requestsAndResponses.add(tocItem); + visibleCategories.get(REQUESTS_AND_RESPONSES).add(tocItem); } public void addSettings(TocItem tocItem) { - settings.add(tocItem); + visibleCategories.get(SETTINGS).add(tocItem); } public void addBuilder(TocItem tocItem) { - builders.add(tocItem); + hiddenCategories.get(BUILDERS).add(tocItem); } public void addEnum(TocItem tocItem) { - enums.add(tocItem); + hiddenCategories.get(ENUMS).add(tocItem); } public void addException(TocItem tocItem) { - exceptions.add(tocItem); + hiddenCategories.get(EXCEPTIONS).add(tocItem); } public void addInterface(TocItem tocItem) { - interfaces.add(tocItem); + hiddenCategories.get(INTERFACES).add(tocItem); } public void addMessage(TocItem tocItem) { - messages.add(tocItem); + hiddenCategories.get(MESSAGES).add(tocItem); } public void addUncategorized(TocItem tocItem) { - uncategorized.add(tocItem); + hiddenCategories.get(UNCATEGORIZED).add(tocItem); } public void addPaging(TocItem tocItem) { - paging.add(tocItem); + hiddenCategories.get(PAGING).add(tocItem); } public void addResourceName(TocItem tocItem) { - resourceNames.add(tocItem); + hiddenCategories.get(RESOURCE_NAMES).add(tocItem); } /** Build a list of TocItems for inclusion in the library's table of contents */ public List toList() { List toc = new ArrayList<>(); - if (!clients.isEmpty()) { - toc.add(createCategory(CLIENTS, clients)); - } - if (!requestsAndResponses.isEmpty()) { - toc.add(createCategory(REQUESTS_AND_RESPONSES, requestsAndResponses)); - } - if (!settings.isEmpty()) { - toc.add(createCategory(SETTINGS, settings)); - } - if (!builders.isEmpty() - || !enums.isEmpty() - || !exceptions.isEmpty() - || !interfaces.isEmpty() - || !messages.isEmpty() - || !paging.isEmpty() - || !resourceNames.isEmpty() - || !uncategorized.isEmpty()) { - TocItem allOthers = new TocItem(ALL_OTHERS, ALL_OTHERS, null); - if (!builders.isEmpty()) { - allOthers.getItems().add(createCategory(BUILDERS, builders)); - } - if (!enums.isEmpty()) { - allOthers.getItems().add(createCategory(ENUMS, enums)); - } - if (!exceptions.isEmpty()) { - allOthers.getItems().add(createCategory(EXCEPTIONS, exceptions)); + + visibleCategories.forEach((name, category) -> { + if (! category.isEmpty()) { + toc.add(createCategory(name, category)); } - if (!messages.isEmpty()) { - allOthers.getItems().add(createCategory(MESSAGES, messages)); - } - if (!paging.isEmpty()) { - allOthers.getItems().add(createCategory(PAGING, paging)); - } - if (!resourceNames.isEmpty()) { - allOthers.getItems().add(createCategory(RESOURCE_NAMES, resourceNames)); - } - if (!interfaces.isEmpty()) { - allOthers.getItems().add(createCategory(INTERFACES, interfaces)); - } - if (!uncategorized.isEmpty()) { - allOthers.getItems().add(createCategory(UNCATEGORIZED, uncategorized)); + }); + + TocItem allOthers = new TocItem(ALL_OTHERS, ALL_OTHERS, null); + hiddenCategories.forEach((name, category) -> { + if (! category.isEmpty()) { + allOthers.getItems().add(createCategory(name, category)); } + }); + if (allOthers.getItems().size() > 0) { toc.add(allOthers); } + return toc; } diff --git a/third_party/docfx-doclet-143274/src/test/java/com/microsoft/model/ApiVersionPackageTocTest.java b/third_party/docfx-doclet-143274/src/test/java/com/microsoft/model/ApiVersionPackageTocTest.java new file mode 100644 index 00000000..7abe3093 --- /dev/null +++ b/third_party/docfx-doclet-143274/src/test/java/com/microsoft/model/ApiVersionPackageTocTest.java @@ -0,0 +1,72 @@ +package com.microsoft.model; + +import static com.google.common.truth.Truth.assertThat; + +import java.util.List; +import org.junit.Test; + +public class ApiVersionPackageTocTest { + private static final TocItem TOC_ITEM = new TocItem("a", "b", ""); + + private final ApiVersionPackageToc toc = new ApiVersionPackageToc(); + + @Test + public void testUncategorized() { + toc.addUncategorized(TOC_ITEM); + List tocItems = toc.toList(); + + assertThat(tocItems).hasSize(1); + + TocItem allOthers = tocItems.get(0); + assertThat(allOthers.getName()).isEqualTo(ApiVersionPackageToc.ALL_OTHERS); + assertThat(allOthers.getItems()).hasSize(1); + + TocItem uncategorized = allOthers.getItems().get(0); + assertThat(uncategorized.getName()).isEqualTo(ApiVersionPackageToc.UNCATEGORIZED); + assertThat(uncategorized.getItems()).hasSize(1); + assertThat(uncategorized.getItems().get(0)).isEqualTo(TOC_ITEM); + } + + @Test + public void testClients() { + toc.addClient(TOC_ITEM); + List tocItems = toc.toList(); + + assertThat(tocItems).hasSize(1); + + TocItem clients = tocItems.get(0); + assertThat(clients.getName()).isEqualTo(ApiVersionPackageToc.CLIENTS); + assertThat(clients.getItems()).hasSize(1); + assertThat(clients.getItems().get(0)).isEqualTo(TOC_ITEM); + } + + + @Test + public void testVisibleAndHidden() { + toc.addRequestOrResponse(TOC_ITEM); + toc.addSettings(new TocItem("TestSettings", "TestSettings", "")); + toc.addInterface(new TocItem("iTest", "iTest", "")); + + List tocItems = toc.toList(); + + assertThat(tocItems).hasSize(3); + + TocItem reqsAndResponses = tocItems.get(0); + assertThat(reqsAndResponses.getName()).isEqualTo(ApiVersionPackageToc.REQUESTS_AND_RESPONSES); + assertThat(reqsAndResponses.getItems()).hasSize(1); + assertThat(reqsAndResponses.getItems().get(0)).isEqualTo(TOC_ITEM); + + TocItem settings = tocItems.get(1); + assertThat(settings.getName()).isEqualTo(ApiVersionPackageToc.SETTINGS); + assertThat(settings.getItems()).hasSize(1); + assertThat(settings.getItems().get(0).getName()).isEqualTo("TestSettings"); + + TocItem allOthers = tocItems.get(2); + assertThat(allOthers.getName()).isEqualTo(ApiVersionPackageToc.ALL_OTHERS); + assertThat(allOthers.getItems()).hasSize(1); + TocItem uncategorized = allOthers.getItems().get(0); + assertThat(uncategorized.getName()).isEqualTo(ApiVersionPackageToc.INTERFACES); + assertThat(uncategorized.getItems()).hasSize(1); + assertThat(uncategorized.getItems().get(0).getName()).isEqualTo("iTest"); + } +} From 07e7feb0ff9a2e1867e15cbc3432fcabb507caf0 Mon Sep 17 00:00:00 2001 From: Burke Davison Date: Mon, 2 Oct 2023 11:35:51 -0400 Subject: [PATCH 10/15] chore: formatting --- .../microsoft/model/ApiVersionPackageToc.java | 28 ++++++++++--------- .../model/ApiVersionPackageTocTest.java | 1 - 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java index fd09ca4b..bbaa66d4 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java @@ -21,7 +21,7 @@ public class ApiVersionPackageToc { private final LinkedHashMap> visibleCategories = new LinkedHashMap<>(); private final LinkedHashMap> hiddenCategories = new LinkedHashMap<>(); - + public ApiVersionPackageToc() { // Order here determines final organization order. visibleCategories.put(CLIENTS, new ArrayList<>()); @@ -37,7 +37,7 @@ public ApiVersionPackageToc() { hiddenCategories.put(INTERFACES, new ArrayList<>()); hiddenCategories.put(UNCATEGORIZED, new ArrayList<>()); } - + public void addClient(TocItem tocItem) { visibleCategories.get(CLIENTS).add(tocItem); } @@ -85,19 +85,21 @@ public void addResourceName(TocItem tocItem) { /** Build a list of TocItems for inclusion in the library's table of contents */ public List toList() { List toc = new ArrayList<>(); - - visibleCategories.forEach((name, category) -> { - if (! category.isEmpty()) { - toc.add(createCategory(name, category)); - } - }); + + visibleCategories.forEach( + (name, category) -> { + if (!category.isEmpty()) { + toc.add(createCategory(name, category)); + } + }); TocItem allOthers = new TocItem(ALL_OTHERS, ALL_OTHERS, null); - hiddenCategories.forEach((name, category) -> { - if (! category.isEmpty()) { - allOthers.getItems().add(createCategory(name, category)); - } - }); + hiddenCategories.forEach( + (name, category) -> { + if (!category.isEmpty()) { + allOthers.getItems().add(createCategory(name, category)); + } + }); if (allOthers.getItems().size() > 0) { toc.add(allOthers); } diff --git a/third_party/docfx-doclet-143274/src/test/java/com/microsoft/model/ApiVersionPackageTocTest.java b/third_party/docfx-doclet-143274/src/test/java/com/microsoft/model/ApiVersionPackageTocTest.java index 7abe3093..ffb44583 100644 --- a/third_party/docfx-doclet-143274/src/test/java/com/microsoft/model/ApiVersionPackageTocTest.java +++ b/third_party/docfx-doclet-143274/src/test/java/com/microsoft/model/ApiVersionPackageTocTest.java @@ -40,7 +40,6 @@ public void testClients() { assertThat(clients.getItems().get(0)).isEqualTo(TOC_ITEM); } - @Test public void testVisibleAndHidden() { toc.addRequestOrResponse(TOC_ITEM); From b739126c7bc16d22c250104972ee197f426bf608 Mon Sep 17 00:00:00 2001 From: Burke Davison Date: Thu, 5 Oct 2023 13:32:35 -0400 Subject: [PATCH 11/15] feat: organize stub packages into single group --- .../com/microsoft/build/YmlFilesBuilder.java | 6 +++- .../expected-generated-files/toc.yml | 31 ++++++++++--------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/YmlFilesBuilder.java b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/YmlFilesBuilder.java index e8747815..3d83005f 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/YmlFilesBuilder.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/YmlFilesBuilder.java @@ -197,9 +197,13 @@ private TocItem buildPackage(PackageElement element) { .addAll(classBuilder.buildFilesForPackage(element, classMetadataFiles)); // build stubs + TocItem stubPackagesItem = new TocItem("Stub packages", "Stub packages", ""); packageLookup .findStubPackages(element, allPackages) - .forEach((PackageElement stub) -> packageTocItem.getItems().add(buildPackage(stub))); + .forEach((PackageElement stub) -> stubPackagesItem.getItems().add(buildPackage(stub))); + if (!stubPackagesItem.getItems().isEmpty()) { + packageTocItem.getItems().add(stubPackagesItem); + } return packageTocItem; } diff --git a/third_party/docfx-doclet-143274/src/test/resources/expected-generated-files/toc.yml b/third_party/docfx-doclet-143274/src/test/resources/expected-generated-files/toc.yml index c6e70146..13ceca3c 100644 --- a/third_party/docfx-doclet-143274/src/test/resources/expected-generated-files/toc.yml +++ b/third_party/docfx-doclet-143274/src/test/resources/expected-generated-files/toc.yml @@ -118,22 +118,25 @@ items: - uid: "com.microsoft.samples.google.v1.SpeechClient" name: "SpeechClient" - - uid: "com.microsoft.samples.google.v1.stub" - name: "com.microsoft.samples.google.v1.stub" + - uid: "Stub packages" + name: "Stub packages" items: - uid: "com.microsoft.samples.google.v1.stub" - name: "Package summary" - - heading: "Classes" - - uid: "com.microsoft.samples.google.v1.stub.GrpcSpeechStub" - name: "GrpcSpeechStub" - - uid: "com.microsoft.samples.google.v1.stub.HttpJsonSpeechStub" - name: "HttpJsonSpeechStub" - - uid: "com.microsoft.samples.google.v1.stub.SpeechStub" - name: "SpeechStub" - - uid: "com.microsoft.samples.google.v1.stub.SpeechStubSettings" - name: "SpeechStubSettings" - - uid: "com.microsoft.samples.google.v1.stub.SpeechStubSettings.Builder" - name: "SpeechStubSettings.Builder" + name: "com.microsoft.samples.google.v1.stub" + items: + - uid: "com.microsoft.samples.google.v1.stub" + name: "Package summary" + - heading: "Classes" + - uid: "com.microsoft.samples.google.v1.stub.GrpcSpeechStub" + name: "GrpcSpeechStub" + - uid: "com.microsoft.samples.google.v1.stub.HttpJsonSpeechStub" + name: "HttpJsonSpeechStub" + - uid: "com.microsoft.samples.google.v1.stub.SpeechStub" + name: "SpeechStub" + - uid: "com.microsoft.samples.google.v1.stub.SpeechStubSettings" + name: "SpeechStubSettings" + - uid: "com.microsoft.samples.google.v1.stub.SpeechStubSettings.Builder" + name: "SpeechStubSettings.Builder" - uid: "com.microsoft.samples.offers" name: "com.microsoft.samples.offers" items: From e162a00be4641b645a0d785f266a8f584414e4ea Mon Sep 17 00:00:00 2001 From: Burke Davison Date: Fri, 6 Oct 2023 13:57:24 -0400 Subject: [PATCH 12/15] feat: organize stub package contents --- .../com/microsoft/build/ClassBuilder.java | 29 +++++++++ .../com/microsoft/model/StubPackageToc.java | 59 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/StubPackageToc.java diff --git a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java index 9bf2e371..615ee5ca 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/ClassBuilder.java @@ -24,6 +24,7 @@ import com.microsoft.model.ApiVersionPackageToc; import com.microsoft.model.MetadataFile; import com.microsoft.model.MetadataFileItem; +import com.microsoft.model.StubPackageToc; import com.microsoft.model.TocItem; import com.microsoft.model.TocTypeMap; import com.microsoft.util.ElementUtil; @@ -69,6 +70,11 @@ List buildFilesForPackage(PackageElement pkg, List classM buildFilesForApiVersionPackage(pkg, apiVersionPackageToc, classMetadataFiles); return apiVersionPackageToc.toList(); + } else if (packageLookup.isApiVersionStubPackage(pkg)) { + StubPackageToc stubPackageToc = new StubPackageToc(); + buildFilesForStubPackage(pkg, stubPackageToc, classMetadataFiles); + return stubPackageToc.toList(); + } else { // Standard package organization is a flat list organized by Java type TocTypeMap typeMap = new TocTypeMap(); @@ -118,6 +124,29 @@ private void buildFilesForApiVersionPackage( } } + private void buildFilesForStubPackage( + Element element, StubPackageToc packageToc, List classMetadataFiles) { + for (TypeElement classElement : elementUtil.extractSortedElements(element)) { + String uid = classLookup.extractUid(classElement); + String name = classLookup.extractTocName(classElement); + String status = classLookup.extractStatus(classElement); + TocItem tocItem = new TocItem(uid, name, status); + + if (name.endsWith("Stub")) { + packageToc.addStub(tocItem); + } else if (name.contains("Settings")) { + packageToc.addSettings(tocItem); + } else if (name.endsWith("CallableFactory")) { + packageToc.addCallableFactory(tocItem); + } else { + packageToc.addUncategorized(tocItem); + } + + classMetadataFiles.add(buildClassYmlFile(classElement)); + buildFilesForStubPackage(classElement, packageToc, classMetadataFiles); + } + } + boolean containsAtLeastOneClient(PackageElement pkg) { return elementUtil.extractSortedElements(pkg).stream().anyMatch(this::isClient); } diff --git a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/StubPackageToc.java b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/StubPackageToc.java new file mode 100644 index 00000000..9d1e4986 --- /dev/null +++ b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/StubPackageToc.java @@ -0,0 +1,59 @@ +package com.microsoft.model; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.List; + +public class StubPackageToc { + static final String STUBS = "Stubs"; + static final String SETTINGS = "Settings"; + static final String CALLABLE_FACTORIES = "Callable factories"; + static final String UNCATEGORIZED = "Other"; + + private final LinkedHashMap> visibleCategories = new LinkedHashMap<>(); + + public StubPackageToc() { + // Order here determines final organization order. + visibleCategories.put(STUBS, new ArrayList<>()); + visibleCategories.put(SETTINGS, new ArrayList<>()); + visibleCategories.put(CALLABLE_FACTORIES, new ArrayList<>()); + } + + public void addStub(TocItem tocItem) { + visibleCategories.get(STUBS).add(tocItem); + } + + public void addSettings(TocItem tocItem) { + visibleCategories.get(SETTINGS).add(tocItem); + } + + public void addCallableFactory(TocItem tocItem) { + visibleCategories.get(CALLABLE_FACTORIES).add(tocItem); + } + + public void addUncategorized(TocItem tocItem) { + visibleCategories.get(UNCATEGORIZED).add(tocItem); + } + + /** Build a list of TocItems for inclusion in the library's table of contents */ + public List toList() { + List toc = new ArrayList<>(); + + visibleCategories.forEach( + (name, category) -> { + if (!category.isEmpty()) { + toc.add(createCategory(name, category)); + } + }); + + return toc; + } + + private TocItem createCategory(String name, List items) { + TocItem category = new TocItem(name, name, null); + items.sort(Comparator.comparing(TocItem::getName)); + category.getItems().addAll(items); + return category; + } +} From 01853d58f5d2d7c4612c1c2913f3b0ffb4b017e5 Mon Sep 17 00:00:00 2001 From: Burke Davison Date: Fri, 6 Oct 2023 14:03:22 -0400 Subject: [PATCH 13/15] fix: update expected toc.yml --- .../expected-generated-files/toc.yml | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/third_party/docfx-doclet-143274/src/test/resources/expected-generated-files/toc.yml b/third_party/docfx-doclet-143274/src/test/resources/expected-generated-files/toc.yml index 13ceca3c..90dec1d0 100644 --- a/third_party/docfx-doclet-143274/src/test/resources/expected-generated-files/toc.yml +++ b/third_party/docfx-doclet-143274/src/test/resources/expected-generated-files/toc.yml @@ -126,17 +126,22 @@ items: - uid: "com.microsoft.samples.google.v1.stub" name: "Package summary" - - heading: "Classes" - - uid: "com.microsoft.samples.google.v1.stub.GrpcSpeechStub" - name: "GrpcSpeechStub" - - uid: "com.microsoft.samples.google.v1.stub.HttpJsonSpeechStub" - name: "HttpJsonSpeechStub" - - uid: "com.microsoft.samples.google.v1.stub.SpeechStub" - name: "SpeechStub" - - uid: "com.microsoft.samples.google.v1.stub.SpeechStubSettings" - name: "SpeechStubSettings" - - uid: "com.microsoft.samples.google.v1.stub.SpeechStubSettings.Builder" - name: "SpeechStubSettings.Builder" + - uid: "Stubs" + name: "Stubs" + items: + - uid: "com.microsoft.samples.google.v1.stub.GrpcSpeechStub" + name: "GrpcSpeechStub" + - uid: "com.microsoft.samples.google.v1.stub.HttpJsonSpeechStub" + name: "HttpJsonSpeechStub" + - uid: "com.microsoft.samples.google.v1.stub.SpeechStub" + name: "SpeechStub" + - uid: "Settings" + name: "Settings" + items: + - uid: "com.microsoft.samples.google.v1.stub.SpeechStubSettings" + name: "SpeechStubSettings" + - uid: "com.microsoft.samples.google.v1.stub.SpeechStubSettings.Builder" + name: "SpeechStubSettings.Builder" - uid: "com.microsoft.samples.offers" name: "com.microsoft.samples.offers" items: From b5ac2b87da1df3185c9beaeea135ee6a42ecc0a7 Mon Sep 17 00:00:00 2001 From: Burke Davison Date: Fri, 6 Oct 2023 15:24:58 -0400 Subject: [PATCH 14/15] chore: place 'Settings' after 'Clients' --- .../src/main/java/com/microsoft/model/ApiVersionPackageToc.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java index bbaa66d4..2e5e7cbf 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/microsoft/model/ApiVersionPackageToc.java @@ -25,8 +25,8 @@ public class ApiVersionPackageToc { public ApiVersionPackageToc() { // Order here determines final organization order. visibleCategories.put(CLIENTS, new ArrayList<>()); - visibleCategories.put(REQUESTS_AND_RESPONSES, new ArrayList<>()); visibleCategories.put(SETTINGS, new ArrayList<>()); + visibleCategories.put(REQUESTS_AND_RESPONSES, new ArrayList<>()); hiddenCategories.put(BUILDERS, new ArrayList<>()); hiddenCategories.put(ENUMS, new ArrayList<>()); From 38d81e3c136fa2aed8acf5a3250e602da4eefc7a Mon Sep 17 00:00:00 2001 From: Burke Davison Date: Fri, 6 Oct 2023 15:28:36 -0400 Subject: [PATCH 15/15] fix: update tests for new category order --- .../microsoft/model/ApiVersionPackageTocTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/third_party/docfx-doclet-143274/src/test/java/com/microsoft/model/ApiVersionPackageTocTest.java b/third_party/docfx-doclet-143274/src/test/java/com/microsoft/model/ApiVersionPackageTocTest.java index ffb44583..693bc87b 100644 --- a/third_party/docfx-doclet-143274/src/test/java/com/microsoft/model/ApiVersionPackageTocTest.java +++ b/third_party/docfx-doclet-143274/src/test/java/com/microsoft/model/ApiVersionPackageTocTest.java @@ -50,16 +50,16 @@ public void testVisibleAndHidden() { assertThat(tocItems).hasSize(3); - TocItem reqsAndResponses = tocItems.get(0); - assertThat(reqsAndResponses.getName()).isEqualTo(ApiVersionPackageToc.REQUESTS_AND_RESPONSES); - assertThat(reqsAndResponses.getItems()).hasSize(1); - assertThat(reqsAndResponses.getItems().get(0)).isEqualTo(TOC_ITEM); - - TocItem settings = tocItems.get(1); + TocItem settings = tocItems.get(0); assertThat(settings.getName()).isEqualTo(ApiVersionPackageToc.SETTINGS); assertThat(settings.getItems()).hasSize(1); assertThat(settings.getItems().get(0).getName()).isEqualTo("TestSettings"); + TocItem reqsAndResponses = tocItems.get(1); + assertThat(reqsAndResponses.getName()).isEqualTo(ApiVersionPackageToc.REQUESTS_AND_RESPONSES); + assertThat(reqsAndResponses.getItems()).hasSize(1); + assertThat(reqsAndResponses.getItems().get(0)).isEqualTo(TOC_ITEM); + TocItem allOthers = tocItems.get(2); assertThat(allOthers.getName()).isEqualTo(ApiVersionPackageToc.ALL_OTHERS); assertThat(allOthers.getItems()).hasSize(1);