10000 refactor: extract and move comment formatting logic to util (#1089) · googleapis/sdk-platform-java@9de65f7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9de65f7

Browse files
authored
refactor: extract and move comment formatting logic to util (#1089)
* Extracts common logic to an util class, and exposes it for reuse * Adds description for echo service explicitly in TestProtoLoader since it is not parsed from source code location as an end-to-end call would (this allows the existing ServiceClientClassTest to cover class header comments that are also formatted with the util’s logic) * Adds ClientLibraryPackageInfoComposerTest as a golden-updating test
1 parent 7a0c7e7 commit 9de65f7

File tree

9 files changed

+264
-85
lines changed

9 files changed

+264
-85
lines changed

gapic-generator-java/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ test_suite(name = "units", tags = ["small"])
183183
GOLDEN_UPDATING_UNIT_TESTS = [
184184
"com.google.api.generator.engine.JavaCodeGeneratorTest",
185185
"com.google.api.generator.gapic.composer.ComposerTest",
186+
"com.google.api.generator.gapic.composer.ClientLibraryPackageInfoComposerTest",
186187
"com.google.api.generator.gapic.composer.common.BatchingDescriptorComposerTest",
187188
"com.google.api.generator.gapic.composer.grpc.GrpcServiceCallableFactoryClassComposerTest",
188189
"com.google.api.generator.gapic.composer.grpc.GrpcServiceStubClassComposerTest",

gapic-generator-java/src/main/java/com/google/api/generator/gapic/composer/ClientLibraryPackageInfoComposer.java

Lines changed: 5 additions & 32 deletions
+
CommentFormatter.formatAsJavaDocComment(
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,13 @@
2424
import com.google.api.generator.gapic.composer.samplecode.SampleCodeWriter;
2525
import com.google.api.generator.gapic.composer.samplecode.ServiceClientHeaderSampleComposer;
2626
import com.google.api.generator.gapic.composer.utils.ClassNames;
27+
import com.google.api.generator.gapic.composer.utils.CommentFormatter;
2728
import com.google.api.generator.gapic.model.GapicContext;
2829
import com.google.api.generator.gapic.model.GapicPackageInfo;
2930
import com.google.api.generator.gapic.model.Sample;
3031
import com.google.api.generator.gapic.model.Service;
3132
import com.google.common.base.Preconditions;
3233
import com.google.common.base.Strings;
33-
import java.util.List;
34-
import java.util.stream.Collectors;
35-
import java.util.stream.Stream;
3634
import javax.annotation.Generated;
3735

3836
public class ClientLibraryPackageInfoComposer {
@@ -80,36 +78,11 @@ private static CommentStatement createPackageInfoJavadoc(GapicContext context) {
8078
javaDocCommentBuilder.addParagraph(
8179
String.format("%s %s %s", DIVIDER, javaClientName, DIVIDER));
8280

83-
// TODO(miraleung): Replace this with a comment converter when we support CommonMark.
8481
if (service.hasDescription()) {
85-
String[] descriptionParagraphs = service.description().split("\\n\\n");
86-
for (int i = 0; i < descriptionParagraphs.length; i++) {
87-
boolean startsWithItemizedList = descriptionParagraphs[i].startsWith(" * ");
88-
// Split by listed items, then join newlines.
89-
List<String> listItems =
90-
Stream.of(descriptionParagraphs[i].split("\\n \\*"))
91-
.map(s -> s.replace("\n", ""))
92-
.collect(Collectors.toList());
93-
if (startsWithItemizedList) {
94-
// Remove the first asterisk.
95-
listItems.set(0, listItems.get(0).substring(2));
96-
}
97-
98-
if (!startsWithItemizedList) {
99-
if (i == 0) {
100-
javaDocCommentBuilder =
101-
javaDocCommentBuilder.addParagraph(
102-
String.format(SERVICE_DESCRIPTION_HEADER_PATTERN, listItems.get(0)));
103-
} else {
104-
javaDocCommentBuilder = javaDocCommentBuilder.addParagraph(listItems.get(0));
105-
}
106-
}
107-
if (listItems.size() > 1 || startsWithItemizedList) {
108-
javaDocCommentBuilder =
109-
javaDocCommentBuilder.addUnorderedList(
110-
listItems.subList(startsWithItemizedList ? 0 : 1, listItems.size()));
111-
}
112-
}
82+
String descriptionComment =
83
84+
service.description(), SERVICE_DESCRIPTION_HEADER_PATTERN);
85+
javaDocCommentBuilder = javaDocCommentBuilder.addUnescapedComment(descriptionComment);
11386
}
11487

11588
javaDocCommentBuilder =

gapic-generator-java/src/main/java/com/google/api/generator/gapic/composer/comment/ServiceClientCommentComposer.java

Lines changed: 11 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,16 @@
1818
import com.google.api.generator.engine.ast.JavaDocComment;
1919
import com.google.api.generator.engine.ast.TypeNode;
2020
import com.google.api.generator.gapic.composer.utils.ClassNames;
21+
import com.google.api.generator.gapic.composer.utils.CommentFormatter;
2122
import com.google.api.generator.gapic.model.Method;
2223
import com.google.api.generator.gapic.model.MethodArgument;
2324
import com.google.api.generator.gapic.model.Service;
2425
import com.google.api.generator.gapic.utils.JavaStyle;
25-
import com.google.common.base.Strings;
2626
import java.util.ArrayList;
2727
import java.util.Arrays;
2828
import java.util.Collections;
2929
import java.util.List;
3030
import java.util.Optional;
31-
import java.util.stream.Collectors;
32-
import java.util.stream.Stream;
3331

3432
public class ServiceClientCommentComposer {
3533
// Tokens.
@@ -120,11 +118,10 @@ public static List<CommentStatement> createClassHeaderComments(
120118
String secondaryTransport) {
121119
JavaDocComment.Builder classHeaderJavadocBuilder = JavaDocComment.builder();
122120
if (service.hasDescription()) {
123-
classHeaderJavadocBuilder =
124-
processProtobufComment(
125-
service.description(),
126-
classHeaderJavadocBuilder,
127-
SERVICE_DESCRIPTION_SUMMARY_PATTERN);
121+
String descriptionComment =
122+
CommentFormatter.formatAsJavaDocComment(
123+
service.description(), SERVICE_DESCRIPTION_SUMMARY_PATTERN);
124+
classHeaderJavadocBuilder = classHeaderJavadocBuilder.addUnescapedComment(descriptionComment);
128125
}
129126

130127
// Service introduction.
@@ -181,8 +178,9 @@ public static List<CommentStatement> createRpcMethodHeaderComment(
181178
JavaDocComment.Builder methodJavadocBuilder = JavaDocComment.builder();
182179

183180
if (method.hasDescription()) {
184-
methodJavadocBuilder =
185-
processProtobufComment(method.description(), methodJavadocBuilder, null);
181+
String descriptionComment =
182+
CommentFormatter.formatAsJavaDocComment(method.description(), null);
183+
methodJavadocBuilder = methodJavadocBuilder.addUnescapedComment(descriptionComment);
186184
}
187185

188186
if (sampleCodeOpt.isPresent()) {
@@ -239,8 +237,9 @@ public static List<CommentStatement> createRpcCallableMethodHeaderComment(
239237
JavaDocComment.Builder methodJavadocBuilder = JavaDocComment.builder();
240238

241239
if (method.hasDescription()) {
242-
methodJavadocBuilder =
243-
processProtobufComment(method.description(), methodJavadocBuilder, null);
240+
String descriptionComment =
241+
CommentFormatter.formatAsJavaDocComment(method.description(), null);
242+
methodJavadocBuilder = methodJavadocBuilder.addUnescapedComment(descriptionComment);
244243
}
245244

246245
methodJavadocBuilder.addParagraph(METHOD_DESCRIPTION_SAMPLE_CODE_SUMMARY_STRING);
@@ -260,42 +259,4 @@ public static List<CommentStatement> createRpcCallableMethodHeaderComment(
260259
private static CommentStatement toSimpleComment(String comment) {
261260
return CommentStatement.withComment(JavaDocComment.withComment(comment));
262261
}
263-
264-
// TODO(miraleung): Replace this with a comment converter when we support CommonMark.
265-
private static JavaDocComment.Builder processProtobufComment(
266-
String rawComment, JavaDocComment.Builder originalCommentBuilder, String firstPattern) {
267-
JavaDocComment.Builder commentBuilder = originalCommentBuilder;
268-
String[] descriptionParagraphs = rawComment.split("\\n\\n");
269-
for (int i = 0; i < descriptionParagraphs.length; i++) {
270-
boolean startsWithItemizedList = descriptionParagraphs[i].startsWith(" * ");
271-
// Split by listed items, then join newlines.
272-
List<String> listItems =
273-
Stream.of(descriptionParagraphs[i].split("\\n \\*"))
274-
.map(s -> s.replace("\n", ""))
275-
.collect(Collectors.toList());
276-
if (startsWithItemizedList) {
277-
// Remove the first asterisk.
278-
listItems.set(0, listItems.get(0).substring(2));
279-
}
280-
if (!startsWithItemizedList) {
281-
if (i == 0) {
282-
if (!Strings.isNullOrEmpty(firstPattern)) {
283-
commentBuilder =
284-
commentBuilder.addParagraph(String.format(firstPattern, listItems.get(0)));
285-
} else {
286-
commentBuilder = commentBuilder.addParagraph(listItems.get(0));
287-
}
288-
} else {
289-
commentBuilder = commentBuilder.addParagraph(listItems.get(0));
290-
}
291-
}
292-
if (listItems.size() > 1 || startsWithItemizedList) {
293-
commentBuilder =
294-
commentBuilder.addUnorderedList(
295-
listItems.subList(startsWithItemizedList ? 0 : 1, listItems.size()));
296-
}
297-
}
298-
299-
return commentBuilder;
300-
}
301262
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.api.generator.gapic.composer.utils;
16+
17+
import com.google.api.generator.engine.ast.JavaDocComment;
18+
import com.google.common.base.Strings;
19+
import java.util.List;
20+
import java.util.stream.Collectors;
21+
import java.util.stream.Stream;
22+
23+
public class CommentFormatter {
24+
25+
private CommentFormatter() {}
26+
27+
// Additional formatting logic for converting protobuf comment to Javadoc
28+
public static String formatAsJavaDocComment(String comment, String prefixPattern) {
29+
30+
JavaDocComment.Builder javaDocCommentBuilder = JavaDocComment.builder();
31+
32+
String[] descriptionParagraphs = comment.split("\\n\\n");
33+
for (int i = 0; i < descriptionParagraphs.length; i++) {
34+
boolean startsWithItemizedList = descriptionParagraphs[i].startsWith(" * ");
35+
// Split by listed items, then join newlines.
36+
List<String> listItems =
37+
Stream.of(descriptionParagraphs[i].split("\\n \\*"))
38+
.map(s -> s.replace("\n", ""))
39+
.collect(Collectors.toList());
40+
if (startsWithItemizedList) {
41+
// Remove the first asterisk.
42+
listItems.set(0, listItems.get(0).substring(2));
43+
}
44+
45+
if (!startsWithItemizedList) {
46+
if (i == 0 && !Strings.isNullOrEmpty(prefixPattern)) {
47+
javaDocCommentBuilder =
48+
javaDocCommentBuilder.addParagraph(String.format(prefixPattern, listItems.get(0)));
49+
} else {
50+
javaDocCommentBuilder = javaDocCommentBuilder.addParagraph(listItems.get(0));
51+
}
52+
}
53+
if (listItems.size() > 1 || startsWithItemizedList) {
54+
javaDocCommentBuilder =
55+
javaDocCommentBuilder.addUnorderedList(
56+
listItems.subList(startsWithItemizedList ? 0 : 1, listItems.size()));
57+
}
58+
}
59+
60+
return javaDocCommentBuilder.build().comment();
61+
}
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.api.generator.gapic.composer;
16+
17+
import com.google.api.generator.engine.writer.JavaWriterVisitor;
18+
import com.google.api.generator.gapic.composer.common.TestProtoLoader;
19+
import com.google.api.generator.gapic.model.GapicContext;
20+
import com.google.api.generator.gapic.model.GapicPackageInfo;
21+
import com.google.api.generator.test.framework.Assert;
22+
import com.google.api.generator.test.framework.Utils;
23+
import java.nio.file.Path;
24+
import java.nio.file.Paths;
25+
import org.junit.Test;
26+
27+
public class ClientLibraryPackageInfoComposerTest {
28+
private GapicContext context = TestProtoLoader.instance().parseShowcaseEcho();
29+
30+
@Test
31+
public void composePackageInfo_showcase() {
32+
GapicPackageInfo packageInfo = ClientLibraryPackageInfoComposer.generatePackageInfo(context);
33+
JavaWriterVisitor visitor = new JavaWriterVisitor();
34+
packageInfo.packageInfo().accept(visitor);
35+
Utils.saveCodegenToFile(this.getClass(), "ShowcaseWithEchoPackageInfo.golden", visitor.write());
36+
Path goldenFilePath =
37+
Paths.get(Utils.getGoldenDir(this.getClass()), "ShowcaseWithEchoPackageInfo.golden");
38+
Assert.assertCodeEquals(goldenFilePath, visitor.write());
39+
}
40+
}

gapic-generator-java/src/test/java/com/google/api/generator/gapic/composer/common/TestProtoLoader.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,18 @@
5151
import java.util.Map;
5252
import java.util.Optional;
5353
import java.util.Set;
54+
import java.util.stream.Collectors;
5455

5556
public class TestProtoLoader {
5657

5758
private static final TestProtoLoader INSTANCE =
5859
new TestProtoLoader(Transport.GRPC, "src/test/resources/");
60+
private static final String ECHO_SERVICE_DESCRIPTION =
61+
"This service is used showcase the four main types of rpcs - unary, server\n"
62+
+ " side streaming, client side streaming, and bidirectional streaming. This\n"
63+
+ " service also exposes methods that explicitly implement server delay, and\n"
64+
+ " paginated calls. Set the 'showcase-trailer' metadata key on any method\n"
65+
+ " to have the values echoed in the response trailers.";
5966
private final String testFilesDirectory;
6067
private final Transport transport;
6168

@@ -136,6 +143,13 @@ public GapicContext parseShowcaseEcho() {
136143
Parser.parseService(
137144
echoFileDescriptor, messageTypes, resourceNames, Optional.empty(), outputResourceNames);
138145

146+
// Explicitly adds service description, since this is not parsed from source code location
147+
// in test protos, as it would from a protoc CodeGeneratorRequest
148+
List<Service> servicesWithDescription =
149+
services.stream()
150+
.map(s -> s.toBuilder().setDescription(ECHO_SERVICE_DESCRIPTION).build())
151+
.collect(Collectors.toList());
152+
139153
String jsonFilename = "showcase_grpc_service_config.json";
140154
Path jsonPath = Paths.get(testFilesDirectory, jsonFilename);
141155
Optional<GapicServiceConfig> configOpt = ServiceConfigParser.parse(jsonPath.toString());
@@ -145,7 +159,7 @@ public GapicContext parseShowcaseEcho() {
145159
return GapicContext.builder()
146160
.setMessages(messageTypes)
147161
.setResourceNames(resourceNames)
148-
.setServices(services)
162+
.setServices(servicesWithDescription)
149163
.setServiceConfig(config)
150164
.setHelperResourceNames(outputResourceNames)
151165
.setTransport(transport)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* The interfaces provided are listed below, along with usage samples.
3+
*
4+
* <p>======================= EchoClient =======================
5+
*
6+
* <p>Service Description: This service is used showcase the four main types of rpcs - unary, server
7+
* side streaming, client side streaming, and bidirectional streaming. This service also exposes
8+
* methods that explicitly implement server delay, and paginated calls. Set the 'showcase-trailer'
9+
* metadata key on any method to have the values echoed in the response trailers.
10+
*
11+
* <p>Sample for EchoClient:
12+
*
13+
* <pre>{@code
14+
* // This snippet has been automatically generated and should be regarded as a code template only.
15+
* // It will require modifications to work:
16+
* // - It may require correct/in-range values for request initialization.
17+
* // - It may require specifying regional endpoints when creating the service client as shown in
18+
* // https://cloud.google.com/java/docs/setup#configure_endpoints_for_the_client_library
19+
* try (EchoClient echoClient = EchoClient.create()) {
20+
* EchoResponse response = echoClient.echo();
21+
* }
22+
* }</pre>
23+
*/
24+
@Generated("by gapic-generator-java")
25+
package com.google.showcase.v1beta1;
26+
27+
import javax.annotation.Generated;

gapic-generator-java/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/EchoClient.golden

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,13 @@ import javax.annotation.Generated;
3030

3131
// AUTO-GENERATED DOCUMENTATION AND CLASS.
3232
/**
33-
* This class provides the ability to make remote calls to the backing service through method calls
34-
* that map to API methods. Sample code to get started:
33+
* Service Description: This service is used showcase the four main types of rpcs - unary, server
34+
* side streaming, client side streaming, and bidirectional streaming. This service also exposes
35+
* methods that explicitly implement server delay, and paginated calls. Set the 'showcase-trailer'
36+
* metadata key on any method to have the values echoed in the response trailers.
37+
*
38+
* <p>This class provides the ability to make remote calls to the backing service through method
39+
* calls that map to API methods. Sample code to get started:
3540
*
3641
* <pre>{@code
3742
* // This snippet has been automatically generated and should be regarded as a code template only.

0 commit comments

Comments
 (0)
0