Skip to content

Commit

Permalink
feat: Left-hand Navigation: Group stub packages under parent (#199)
Browse files Browse the repository at this point in the history
* chore: add stub package for testing

* fix: suppress xlint errors in test sample classes

* chore: add stub package helpers and refactor

* chore: nest stub package within parent

* chore: support child stub packages

* chore: ensure sorted child stub packages

* chore: check for older packages before adding category

* chore: formatting
  • Loading branch information
burkedavison authored Sep 26, 2023
1 parent caf61a8 commit f8ff141
Show file tree
Hide file tree
Showing 21 changed files with 4,719 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static com.microsoft.build.BuilderUtil.populateUidValues;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.microsoft.lookup.ClassItemsLookup;
import com.microsoft.lookup.ClassLookup;
Expand Down Expand Up @@ -77,31 +78,40 @@ public boolean build() {
@VisibleForTesting
class Processor {
// table of contents
final TocFile tocFile = new TocFile(outputPath, projectName, disableChangelog);
private final TocFile tocFile = new TocFile(outputPath, projectName, disableChangelog);
// overview page
final MetadataFile projectMetadataFile = new MetadataFile(outputPath, "overview.yml");
private final MetadataFile projectMetadataFile = new MetadataFile(outputPath, "overview.yml");
// package summary pages
final List<MetadataFile> packageMetadataFiles = new ArrayList<>();
private final List<MetadataFile> packageMetadataFiles = new ArrayList<>();
// packages
final List<MetadataFileItem> packageItems = new ArrayList<>();
private final List<MetadataFileItem> packageItems = new ArrayList<>();
// class/enum/interface/etc. pages
final List<MetadataFile> classMetadataFiles = new ArrayList<>();
private final List<MetadataFile> classMetadataFiles = new ArrayList<>();

private final List<PackageElement> allPackages =
elementUtil.extractPackageElements(environment.getIncludedElements());

@VisibleForTesting
void process() {
ImmutableListMultimap<PackageGroup, PackageElement> organizedPackages =
ImmutableListMultimap<PackageGroup, PackageElement> organizedPackagesWithoutStubs =
packageLookup.organize(
elementUtil.extractPackageElements(environment.getIncludedElements()));
allPackages.stream()
.filter(pkg -> !packageLookup.isApiVersionStubPackage(pkg))
.collect(Collectors.toList()));

for (PackageElement element : organizedPackages.get(PackageGroup.VISIBLE)) {
for (PackageElement element : organizedPackagesWithoutStubs.get(PackageGroup.VISIBLE)) {
tocFile.addTocItem(buildPackage(element));
}

TocItem older = new TocItem(OLDER_AND_PRERELEASE, OLDER_AND_PRERELEASE, null);
for (PackageElement element : organizedPackages.get(PackageGroup.OLDER_AND_PRERELEASE)) {
older.getItems().add(buildPackage(element));
ImmutableList<PackageElement> olderPackages =
organizedPackagesWithoutStubs.get(PackageGroup.OLDER_AND_PRERELEASE);
if (!olderPackages.isEmpty()) {
TocItem older = new TocItem(OLDER_AND_PRERELEASE, OLDER_AND_PRERELEASE, null);
for (PackageElement element : olderPackages) {
older.getItems().add(buildPackage(element));
}
tocFile.addTocItem(older);
}
tocFile.addTocItem(older);

for (MetadataFile packageFile : packageMetadataFiles) {
packageItems.addAll(packageFile.getItems());
Expand Down Expand Up @@ -138,6 +148,11 @@ private TocItem buildPackage(PackageElement element) {
classBuilder.buildFilesForInnerClasses(element, typeMap, classMetadataFiles);
packageTocItem.getItems().addAll(joinTocTypeItems(typeMap));

// build stubs
packageLookup
.findStubPackages(element, allPackages)
.forEach((PackageElement stub) -> packageTocItem.getItems().add(buildPackage(stub)));

return packageTocItem;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
import com.google.docfx.doclet.ApiVersion;
import com.microsoft.lookup.model.ExtendedMetadataFileItem;
import com.microsoft.model.Status;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.lang.model.element.PackageElement;
import jdk.javadoc.doclet.DocletEnvironment;

Expand Down Expand Up @@ -67,15 +69,45 @@ public String extractJavaType(PackageElement element) {
return null;
}

/**
* @return true, if the package ends with 'stub' and its parent package is an API version
*/
public boolean isApiVersionStubPackage(PackageElement pkg) {
return isApiVersionStubPackageName(String.valueOf(pkg.getQualifiedName()));
}

/**
* @return true, if the package ends with 'stub' and its parent package is an API version
*/
@VisibleForTesting
boolean isApiVersionStubPackageName(String name) {
List<String> packagePath = Arrays.asList(name.split("\\."));
int stubIndex = packagePath.indexOf("stub");
if (stubIndex < 1) {
return false;
}
return ApiVersion.parse(packagePath.get(stubIndex - 1)).isPresent();
}

public List<PackageElement> findStubPackages(
PackageElement pkg, Collection<PackageElement> packages) {
String expectedStubPackageBase = pkg.getQualifiedName() + ".stub";
return packages.stream()
.filter(p -> String.valueOf(p.getQualifiedName()).startsWith(expectedStubPackageBase))
.sorted()
.collect(Collectors.toList());
}

/** Compare PackageElements by their parsed ApiVersion */
private final Comparator<PackageElement> byComparingApiVersion =
Comparator.comparing(pkg -> extractApiVersion(pkg).orElse(ApiVersion.NONE));

public Optional<ApiVersion> extractApiVersion(PackageElement pkg) {
String name = String.valueOf(pkg.getQualifiedName());
int lastPackageIndex = name.lastIndexOf('.');
String leafPackage = name.substring(lastPackageIndex + 1);
return ApiVersion.parse(leafPackage);
return extractApiVersion(String.valueOf(pkg.getQualifiedName()));
}

public Optional<ApiVersion> extractApiVersion(String name) {
return ApiVersion.parse(getLeafPackage(name));
}

public enum PackageGroup {
Expand Down Expand Up @@ -132,17 +164,14 @@ Multimap<String, PackageElement> groupVersions(List<PackageElement> packages) {
packages,
(pkg) -> {
String name = String.valueOf(pkg.getQualifiedName());
int lastPackageIndex = name.lastIndexOf('.');
String leafPackage = name.substring(lastPackageIndex + 1);
// For package a.b.c.d, the value of leafPackage is 'd'.

boolean packageIsApiVersion = ApiVersion.parse(leafPackage).isPresent();
// Group all API version packages into a single .v# group
boolean packageIsApiVersion = ApiVersion.parse(getLeafPackage(name)).isPresent();
if (packageIsApiVersion) {
String packageWithoutVersion = name.substring(0, lastPackageIndex);
// For package a.b.c.v1, the value of packageWithoutVersion is a.b.c
return packageWithoutVersion + ".v#"; // Use "v#" package to group all versions
return withoutLeafPackage(name) + ".v#"; // withoutLeafPackage("a.b.c.v1") --> "a.b.c"
}
// Using 'name' ensures this package is placed in a group of size 1.

// When not an API version package, use 'name' to ensure a unique group of size 1.
return name;
});
}
Expand Down Expand Up @@ -174,4 +203,16 @@ PackageElement getRecommended(Collection<PackageElement> packages) {
ApiVersion recommended = ApiVersion.getRecommended(versions.keySet());
return versions.get(recommended);
}

/** withoutLeafPackage("a.b.c.d") --> "a.b.c" */
private String withoutLeafPackage(String name) {
int lastPackageIndex = name.lastIndexOf('.');
return name.substring(0, lastPackageIndex);
}

/** getLeafPackage("a.b.c.d") --> "d" */
private String getLeafPackage(String name) {
int lastPackageIndex = name.lastIndexOf('.');
return name.substring(lastPackageIndex + 1);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.microsoft.doclet;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

Expand Down Expand Up @@ -105,20 +104,6 @@ public void assertSameFileNames(List<Path> expected, List<Path> generated) {
List<String> generatedFilenames =
generated.stream().map(Path::getFileName).map(Path::toString).collect(Collectors.toList());

assertWithMessage("Expected files were not generated.")
.that(
expectedFilenames.stream()
.filter(file -> !generatedFilenames.contains(file))
.collect(Collectors.toList()))
.isEmpty();

assertWithMessage("Files were generated that should not have been.")
.that(
generatedFilenames.stream()
.filter(file -> !expectedFilenames.contains(file))
.collect(Collectors.toList()))
.isEmpty();

assertThat(expected.size()).isEqualTo(generated.size());
assertThat(generatedFilenames).containsExactlyElementsIn(expectedFilenames);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,58 @@ public void testOrganize_WithoutReleasePackage() {
.containsExactly("com.microsoft.samples.google.v1beta");
}

@Test
public void testFindStubPackage() {
ImmutableList<PackageElement> packages =
ImmutableList.of(
elements.getPackageElement("com.microsoft.samples.google.v1"),
elements.getPackageElement("com.microsoft.samples.google.v1.stub"),
elements.getPackageElement("com.microsoft.samples.google.v1beta"),
elements.getPackageElement("com.microsoft.samples.google"));

List<PackageElement> foundStubPackages =
packageLookup.findStubPackages(
elements.getPackageElement("com.microsoft.samples.google.v1"), packages);
assertThat(foundStubPackages).isNotEmpty();
assertThat(foundStubPackages).hasSize(1);
assertThat(toPackageName(foundStubPackages.get(0)))
.isEqualTo("com.microsoft.samples.google.v1.stub");

List<PackageElement> notFoundStubPackageOfStubPackage =
packageLookup.findStubPackages(
elements.getPackageElement("com.microsoft.samples.google.v1.stub"), packages);
assertThat(notFoundStubPackageOfStubPackage).isEmpty();

List<PackageElement> notFoundStubPackage =
packageLookup.findStubPackages(
elements.getPackageElement("com.microsoft.samples.google"), packages);
assertThat(notFoundStubPackage).isEmpty();
}

@Test
public void testIsApiStubPackage() {
assertThat(
packageLookup.isApiVersionStubPackage(
elements.getPackageElement("com.microsoft.samples.google.v1")))
.isFalse();
assertThat(
packageLookup.isApiVersionStubPackage(
elements.getPackageElement("com.microsoft.samples.google.v1.stub")))
.isTrue();
assertThat(
packageLookup.isApiVersionStubPackageName("com.microsoft.samples.google.v1.stub.child"))
.isTrue();

assertThat(packageLookup.isApiVersionStubPackageName("a")).isFalse();
// False due to not being an API version package, even though it ends in .stub
assertThat(packageLookup.isApiVersionStubPackageName("a.stub")).isFalse();
}

private List<String> toPackageNames(List<PackageElement> packages) {
return packages.stream()
.map(pkg -> String.valueOf(pkg.getQualifiedName()))
.collect(Collectors.toList());
return packages.stream().map(this::toPackageName).collect(Collectors.toList());
}

private String toPackageName(PackageElement pkg) {
return String.valueOf(pkg.getQualifiedName());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*
* @deprecated Use {@link AgreementMetaData} instead.
*/
@Deprecated
public class AgreementDetailsCollectionOperations extends BasePartnerComponentString
implements IAgreementDetailsCollection {
/**
Expand All @@ -25,6 +26,7 @@ public AgreementDetailsCollectionOperations(IPartner rootPartnerOperations) {
* @return A list of agreement details.
* @deprecated Some text
*/
@Deprecated
public ResourceCollection<AgreementMetaData> get() {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public void setTemplateId(String value) {
*
* @deprecated
*/
@Deprecated
@JsonProperty("agreementLink")
private String agreementLink;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*
* @deprecated This one is deprecated :(
*/
@Deprecated
public interface IAgreementDetailsCollection {
/**
* Retrieves all current agreement metadata.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
* }</pre>
*/
@Generated("by gapic-generator-java")
@SuppressWarnings("unchecked")
public class ProductSearchSettings extends ClientSettings<ProductSearchSettings> {

/** Returns the object with the settings used for calls to createProductSet. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
*/
@BetaApi
@Generated("by gapic-generator-java")
@SuppressWarnings("unchecked")
public class SpeechSettings extends ClientSettings<SpeechSettings> {

/** Returns the object with the settings used for calls to recognize. */
Expand Down
Loading

0 comments on commit f8ff141

Please sign in to comment.