Skip to content

Commit 89a08c4

Browse files
authored
feat: add new library overview page (#198)
* feat: add new library overview page * fix linting issues * remove extra file * get versions and file as environment variables * fix linting errors * update repoMetadatFilePath * fix lint * add tests, refactor RepoMetadata * fix lint * add in dynamic recommendedApiVersion * update exception
1 parent 251c5e5 commit 89a08c4

18 files changed

Lines changed: 736 additions & 88 deletions

File tree

third_party/docfx-doclet-143274/pom.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,11 @@
154154
<artifactId>guava</artifactId>
155155
<version>32.1.2-jre</version>
156156
</dependency>
157+
<dependency>
158+
<groupId>com.google.code.gson</groupId>
159+
<artifactId>gson</artifactId>
160+
<version>2.10.1</version>
161+
</dependency>
157162

158163
<!-- Test dependencies -->
159164
<dependency>
@@ -186,6 +191,12 @@
186191
<version>4.18.0</version>
187192
<scope>test</scope>
188193
</dependency>
194+
<dependency>
195+
<groupId>com.github.stefanbirkner</groupId>
196+
<artifactId>system-rules</artifactId>
197+
<version>1.19.0</version>
198+
<scope>test</scope>
199+
</dependency>
189200
</dependencies>
190201

191202
<repositories>
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package com.google.docfx.doclet;
2+
3+
// This parses .repo-metadata.json files to create a new library overview
4+
5+
import com.google.gson.Gson;
6+
import com.google.gson.annotations.SerializedName;
7+
import java.io.FileReader;
8+
import java.io.IOException;
9+
import java.util.Objects;
10+
11+
public class RepoMetadata {
12+
13+
@SerializedName("api_shortname")
14+
private String apiShortName;
15+
16+
@SerializedName("name_pretty")
17+
private String namePretty;
18+
19+
@SerializedName("product_documentation")
20+
private String productDocumentationUri;
21+
22+
@SerializedName("api_description")
23+
private String apiDescription;
24+
25+
@SerializedName("client_documentation")
26+
private String clientDocumentationUri;
27+
28+
@SerializedName("repo")
29+
private String repo;
30+
31+
@SerializedName("repo_short")
32+
private String repoShort;
33+
34+
@SerializedName("distribution_name")
35+
private String distributionName;
36+
37+
@SerializedName("api_id")
38+
private String apiId;
39+
40+
private String artifactId;
41+
42+
public String getNamePretty() {
43+
return this.namePretty;
44+
}
45+
46+
public void setNamePretty(String namePretty) {
47+
this.namePretty = namePretty;
48+
}
49+
50+
public String getApiShortName() {
51+
return this.apiShortName;
52+
}
53+
54+
public void setApiShortName(String apiShortName) {
55+
this.apiShortName = apiShortName;
56+
}
57+
58+
public String getProductDocumentationUri() {
59+
return this.productDocumentationUri;
60+
}
61+
62+
public void setProductDocumentationUri(String productDocumentationUri) {
63+
this.productDocumentationUri = productDocumentationUri;
64+
}
65+
66+
public String getApiDescription() {
67+
return this.apiDescription;
68+
}
69+
70+
public void setApiDescription(String apiDescription) {
71+
this.apiDescription = apiDescription;
72+
}
73+
74+
public String getClientDocumentationUri() {
75+
return this.clientDocumentationUri;
76+
}
77+
78+
public void setClientDocumentationUri(String clientDocumentationUri) {
79+
this.clientDocumentationUri = clientDocumentationUri;
80+
}
81+
82+
public String getRepo() {
83+
return this.repo;
84+
}
85+
86+
public void setRepo(String repo) {
87+
this.repo = repo;
88+
}
89+
90+
public String getRepoShort() {
91+
return this.repoShort;
92+
}
93+
94+
public void setRepoShort(String repoShort) {
95+
this.repoShort = repoShort;
96+
}
97+
98+
public String getDistributionName() {
99+
return this.distributionName;
100+
}
101+
102+
public void setDistributionName(String distributionName) {
103+
this.distributionName = distributionName;
104+
}
105+
106+
public String getApiId() {
107+
return this.apiId;
108+
}
109+
110+
public void setApiId(String apiId) {
111+
this.apiId = apiId;
112+
}
113+
114+
// artifactId is parsed from distributionName
115+
public String getArtifactId() {
116+
String substrings[] = this.distributionName.split(":");
117+
return substrings[substrings.length - 1];
118+
}
119+
120+
// GithubLink is created from repo and repoShort
121+
public String getGithubLink() {
122+
String githubRootUri = "https://github.com/";
123+
String githubLink = githubRootUri + repo;
124+
if (Objects.equals(this.repo, "googleapis/google-cloud-java")
125+
|| Objects.equals(this.repo, "googleapis/sdk-platform-java")) {
126+
githubLink = githubLink + "/tree/main/" + this.repoShort;
127+
}
128+
return githubLink;
129+
}
130+
131+
// MavenLink is created from distributionName
132+
public String getMavenLink() {
133+
String mavenRootUri = "https://central.sonatype.com/artifact/";
134+
String substrings[] = this.distributionName.split(":");
135+
String groupName = substrings[0];
136+
String artifactId = substrings[substrings.length - 1];
137+
String mavenLink = mavenRootUri + groupName + "/" + artifactId;
138+
return mavenLink;
139+
}
140+
141+
public RepoMetadata parseRepoMetadata(String fileName) {
142+
Gson gson = new Gson();
143+
try (FileReader reader = new FileReader(fileName)) {
144+
return gson.fromJson(reader, RepoMetadata.class);
145+
} catch (IOException e) {
146+
throw new RuntimeException(".repo-metadata.json is not found", e);
147+
}
148+
}
149+
}

third_party/docfx-doclet-143274/src/main/java/com/microsoft/build/YmlFilesBuilder.java

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
import com.google.common.annotations.VisibleForTesting;
66
import com.google.common.collect.ImmutableList;
77
import com.google.common.collect.ImmutableListMultimap;
8+
import com.google.docfx.doclet.ApiVersion;
89
import com.microsoft.lookup.ClassItemsLookup;
910
import com.microsoft.lookup.ClassLookup;
1011
import com.microsoft.lookup.PackageLookup;
1112
import com.microsoft.lookup.PackageLookup.PackageGroup;
13+
import com.microsoft.model.LibraryOverviewFile;
1214
import com.microsoft.model.MetadataFile;
1315
import com.microsoft.model.MetadataFileItem;
1416
import com.microsoft.model.TocFile;
@@ -17,6 +19,7 @@
1719
import com.microsoft.util.ElementUtil;
1820
import com.microsoft.util.FileUtil;
1921
import java.util.ArrayList;
22+
import java.util.HashSet;
2023
import java.util.List;
2124
import java.util.stream.Collectors;
2225
import javax.lang.model.element.PackageElement;
@@ -31,6 +34,14 @@ public class YmlFilesBuilder {
3134
private final PackageLookup packageLookup;
3235
private final String projectName;
3336
private final boolean disableChangelog;
37+
38+
private final boolean disableLibraryOverview;
39+
40+
private final String artifactVersion;
41+
42+
private final String librariesBomVersion;
43+
44+
private final String repoMetadataFilePath;
3445
private final ProjectBuilder projectBuilder;
3546
private final PackageBuilder packageBuilder;
3647
private final ClassBuilder classBuilder;
@@ -42,13 +53,21 @@ public YmlFilesBuilder(
4253
String[] excludePackages,
4354
String[] excludeClasses,
4455
String projectName,
45-
boolean disableChangelog) {
56+
boolean disableChangelog,
57+
boolean disableLibraryOverview,
58+
String artifactVersion,
59+
String librariesBomVersion,
60+
String repoMetadataFilePath) {
4661
this.environment = environment;
4762
this.outputPath = outputPath;
63+
this.artifactVersion = artifactVersion;
64+
this.librariesBomVersion = librariesBomVersion;
65+
this.repoMetadataFilePath = repoMetadataFilePath;
4866
this.elementUtil = new ElementUtil(excludePackages, excludeClasses);
4967
this.packageLookup = new PackageLookup(environment);
5068
this.projectName = projectName;
5169
this.disableChangelog = disableChangelog;
70+
this.disableLibraryOverview = disableLibraryOverview;
5271
this.projectBuilder = new ProjectBuilder(projectName);
5372
ClassLookup classLookup = new ClassLookup(environment, elementUtil);
5473
this.referenceBuilder = new ReferenceBuilder(environment, classLookup, elementUtil);
@@ -67,20 +86,35 @@ public boolean build() {
6786
processor.process();
6887

6988
// write to yaml files
70-
FileUtil.dumpToFile(processor.projectMetadataFile);
89+
if (disableLibraryOverview) {
90+
FileUtil.dumpToFile(processor.projectMetadataFile);
91+
}
7192
processor.packageMetadataFiles.forEach(FileUtil::dumpToFile);
7293
processor.classMetadataFiles.forEach(FileUtil::dumpToFile);
7394
FileUtil.dumpToFile(processor.tocFile);
7495

96+
// Generate new library overview page
97+
if (!disableLibraryOverview) {
98+
LibraryOverviewFile libraryOverviewFile =
99+
new LibraryOverviewFile(
100+
outputPath,
101+
"overview.md",
102+
artifactVersion,
103+
librariesBomVersion,
104+
repoMetadataFilePath,
105+
processor.recommendedApiVersion);
106+
FileUtil.dumpToFile(libraryOverviewFile);
107+
}
75108
return true;
76109
}
77110

78111
@VisibleForTesting
79112
class Processor {
80113
// table of contents
81-
private final TocFile tocFile = new TocFile(outputPath, projectName, disableChangelog);
82-
// overview page
83-
private final MetadataFile projectMetadataFile = new MetadataFile(outputPath, "overview.yml");
114+
final TocFile tocFile =
115+
new TocFile(outputPath, projectName, disableChangelog, disableLibraryOverview);
116+
// overview page if not using new libraryOverview
117+
final MetadataFile projectMetadataFile = new MetadataFile(outputPath, "overview.yml");
84118
// package summary pages
85119
private final List<MetadataFile> packageMetadataFiles = new ArrayList<>();
86120
// packages
@@ -91,6 +125,8 @@ class Processor {
91125
private final List<PackageElement> allPackages =
92126
elementUtil.extractPackageElements(environment.getIncludedElements());
93127

128+
private String recommendedApiVersion = "";
129+
94130
@VisibleForTesting
95131
void process() {
96132
ImmutableListMultimap<PackageGroup, PackageElement> organizedPackagesWithoutStubs =
@@ -99,6 +135,13 @@ void process() {
99135
.filter(pkg -> !packageLookup.isApiVersionStubPackage(pkg))
100136
.collect(Collectors.toList()));
101137

138+
// Get recommended ApiVersion for new Library Overview
139+
HashSet<ApiVersion> versions = new HashSet<>();
140+
for (PackageElement pkg : allPackages) {
141+
packageLookup.extractApiVersion(pkg).ifPresent(versions::add);
142+
}
143+
recommendedApiVersion = ApiVersion.getRecommended(versions).toString();
144+
102145
for (PackageElement element : organizedPackagesWithoutStubs.get(PackageGroup.VISIBLE)) {
103146
tocFile.addTocItem(buildPackage(element));
104147
}
@@ -125,8 +168,10 @@ void process() {
125168
}
126169
}
127170
}
128-
// build project summary page
129-
projectBuilder.buildProjectMetadataFile(packageItems, projectMetadataFile);
171+
// build project summary page if disableLibraryOverview=true
172+
if (disableLibraryOverview) {
173+
projectBuilder.buildProjectMetadataFile(packageItems, projectMetadataFile);
174+
}
130175

131176
// post-processing
132177
populateUidValues(packageMetadataFiles, classMetadataFiles);

third_party/docfx-doclet-143274/src/main/java/com/microsoft/doclet/DocFxDoclet.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,30 @@ public void init(Locale locale, Reporter reporter) {
2121

2222
@Override
2323
public boolean run(DocletEnvironment environment) {
24+
String artifactVersion = System.getenv("artifactVersion");
25+
String librariesBomVersion = System.getenv("librariesBomVersion");
26+
String repoMetadataFilePath = System.getenv("repoMetadataFilePath");
27+
reporter.print(Kind.NOTE, "Environment variable artifactVersion: " + artifactVersion);
28+
reporter.print(Kind.NOTE, "Environment variable librariesBomVersion: " + librariesBomVersion);
29+
reporter.print(Kind.NOTE, "Environment variable repoMetadataFilePath: " + repoMetadataFilePath);
2430
reporter.print(Kind.NOTE, "Output path: " + outputPath);
2531
reporter.print(Kind.NOTE, "Excluded packages: " + Arrays.toString(excludePackages));
2632
reporter.print(Kind.NOTE, "Excluded classes: " + Arrays.toString(excludeClasses));
2733
reporter.print(Kind.NOTE, "Project name: " + projectName);
2834
reporter.print(Kind.NOTE, "Disable changelog: " + disableChangelog);
35+
reporter.print(Kind.NOTE, "Disable libraryOverview: " + disableLibraryOverview);
2936

3037
return (new YmlFilesBuilder(
3138
environment,
3239
outputPath,
3340
excludePackages,
3441
excludeClasses,
3542
projectName,
36-
disableChangelog))
43+
disableChangelog,
44+
disableLibraryOverview,
45+
artifactVersion,
46+
librariesBomVersion,
47+
repoMetadataFilePath))
3748
.build();
3849
}
3950

@@ -47,6 +58,7 @@ public String getName() {
4758
private String[] excludeClasses = {};
4859
private String projectName;
4960
private boolean disableChangelog;
61+
private boolean disableLibraryOverview;
5062

5163
@Override
5264
public Set<? extends Option> getSupportedOptions() {
@@ -102,6 +114,21 @@ public boolean process(String option, List<String> arguments) {
102114
return true;
103115
}
104116
},
117+
new CustomOption(
118+
"Disable libraryOverview",
119+
Arrays.asList("-disable-libraryOverview", "--disable-libraryOverview"),
120+
"disablelibraryOverview") {
121+
@Override
122+
public boolean process(String option, List<String> arguments) {
123+
if (arguments.get(0).equalsIgnoreCase("false")) {
124+
disableLibraryOverview = false;
125+
} else {
126+
disableLibraryOverview = true;
127+
}
128+
return true;
129+
}
130+
},
131+
105132
// Support next properties for compatibility with Gradle javadoc task.
106133
// According to javadoc spec - these properties used by StandardDoclet and used only when
107134
// 'doclet' parameter not populated. But Gradle javadoc not align with this rule and

0 commit comments

Comments
 (0)