Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0aa8336

Browse files
authored
[ggj] feat: flatten sigs, handle wildcards, update Client methods (#160)
* feat: add initial resource name def parsing * feat: add early failure for missing fields * feat: couple resnames and message parsing * fix!: refactor method arg parsing away from class creation * feat: add resource_reference parsing * fix: dot name parsing * feat: extract arg resource names and parse parents * feat: flatten sigs, handle wildcards, update Client methods
1 parent 8e31e27 commit 0aa8336

File tree

13 files changed

+550
-82
lines changed

13 files changed

+550
-82
lines changed

src/main/java/com/google/api/generator/gapic/model/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ java_library(
1313
deps = [
1414
"//src/main/java/com/google/api/generator:autovalue",
1515
"//src/main/java/com/google/api/generator/engine/ast",
16+
"//src/main/java/com/google/api/generator/gapic/utils",
1617
"@com_google_auto_value_auto_value//jar",
1718
"@com_google_auto_value_auto_value_annotations//jar",
1819
"@com_google_code_findbugs_jsr305//jar",

src/main/java/com/google/api/generator/gapic/model/MethodArgument.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,13 @@ public abstract class MethodArgument {
2929
// appeared as the last element).
3030
public abstract ImmutableList<TypeNode> nestedTypes();
3131

32+
// Returns true if this is a resource name helper tyep.
33+
public abstract boolean isResourceNameHelper();
34+
3235
public static Builder builder() {
33-
return new AutoValue_MethodArgument.Builder().setNestedTypes(ImmutableList.of());
36+
return new AutoValue_MethodArgument.Builder()
37+
.setNestedTypes(ImmutableList.of())
38+
.setIsResourceNameHelper(false);
3439
}
3540

3641
@AutoValue.Builder
@@ -41,6 +46,8 @@ public abstract static class Builder {
4146

4247
public abstract Builder setNestedTypes(List<TypeNode> nestedTypes);
4348

49+
public abstract Builder setIsResourceNameHelper(boolean isResourceNameHelper);
50+
4451
public abstract MethodArgument build();
4552
}
4653
}

src/main/java/com/google/api/generator/gapic/model/ResourceName.java

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
import com.google.api.generator.engine.ast.TypeNode;
1818
import com.google.api.generator.engine.ast.VaporReference;
19+
import com.google.api.generator.gapic.utils.JavaStyle;
20+
import com.google.api.generator.gapic.utils.ResourceNameConstants;
1921
import com.google.auto.value.AutoValue;
2022
import com.google.common.collect.ImmutableList;
2123
import java.util.List;
@@ -45,6 +47,8 @@ public abstract class ResourceName {
4547
// The Java TypeNode of the resource name helper class to generate.
4648
public abstract TypeNode type();
4749

50+
public abstract boolean isOnlyWildcard();
51+
4852
// The message in which this resource was defined. Optional.
4953
// This is expected to be empty for file-level definitions.
5054
@Nullable
@@ -55,7 +59,27 @@ public boolean hasParentMessageName() {
5559
}
5660

5761
public static Builder builder() {
58-
return new AutoValue_ResourceName.Builder();
62+
63+
return new AutoValue_ResourceName.Builder().setIsOnlyWildcard(false);
64+
}
65+
66+
public static ResourceName createWildcard(String resourceTypeString, String pakkage) {
67+
String placeholderVarName =
68+
JavaStyle.toLowerCamelCase(
69+
resourceTypeString.substring(resourceTypeString.indexOf(SLASH) + 1));
70+
return builder()
71+
.setVariableName(placeholderVarName)
72+
.setPakkage(pakkage)
73+
.setResourceTypeString(resourceTypeString)
74+
.setPatterns(ImmutableList.of(ResourceNameConstants.WILDCARD_PATTERN))
75+
.setIsOnlyWildcard(true)
76+
.setType(
77+
TypeNode.withReference(
78+
VaporReference.builder()
79+
.setName("ResourceName")
80+
.setPakkage("com.google.api.resourcenames")
81+
.build()))
82+
.build();
5983
}
6084

6185
@Override
@@ -98,22 +122,32 @@ public abstract static class Builder {
98122

99123
public abstract Builder setParentMessageName(String parentMessageName);
100124

101-
// Private setter.
125+
// Private setters.
102126
abstract Builder setType(TypeNode type);
103127

128+
abstract Builder setIsOnlyWildcard(boolean isOnlyWildcard);
129+
104130
// Private accessors.
105131
abstract String pakkage();
106132

107133
abstract String resourceTypeString();
108134

135+
abstract boolean isOnlyWildcard();
136+
109137
// Private.
110138
abstract ResourceName autoBuild();
111139

112140
public ResourceName build() {
113-
String typeName = resourceTypeString().substring(resourceTypeString().lastIndexOf(SLASH) + 1);
114-
setType(
115-
TypeNode.withReference(
116-
VaporReference.builder().setName(typeName).setPakkage(pakkage()).build()));
141+
if (!isOnlyWildcard()) {
142+
String typeName =
143+
resourceTypeString().substring(resourceTypeString().lastIndexOf(SLASH) + 1);
144+
setType(
145+
TypeNode.withReference(
146+
VaporReference.builder()
147+
.setName(String.format("%sName", typeName))
148+
.setPakkage(pakkage())
149+
.build()));
150+
}
117151
return autoBuild();
118152
}
119153
}

src/main/java/com/google/api/generator/gapic/protoparser/MethodSignatureParser.java

Lines changed: 99 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
import com.google.api.generator.gapic.model.Message;
2121
import com.google.api.generator.gapic.model.MethodArgument;
2222
import com.google.api.generator.gapic.model.ResourceName;
23+
import com.google.common.annotations.VisibleForTesting;
2324
import com.google.common.base.Preconditions;
25+
import com.google.common.collect.Lists;
2426
import com.google.protobuf.Descriptors.MethodDescriptor;
2527
import java.util.ArrayList;
2628
import java.util.Arrays;
@@ -56,40 +58,89 @@ public static List<List<MethodArgument>> parseMethodSignatures(
5658
Message inputMessage = messageTypes.get(methodInputTypeName);
5759

5860
// Example from Expand in echo.proto:
59-
// Input: ["content,error", "content,error,info"].
60-
// Output: [["content", "error"], ["content", "error", "info"]].
61+
// stringSigs: ["content,error", "content,error,info"].
6162
for (String stringSig : stringSigs) {
62-
List<MethodArgument> arguments = new ArrayList<>();
63-
for (String argumentName : stringSig.split(METHOD_SIGNATURE_DELIMITER)) {
64-
List<TypeNode> argumentTypePath =
65-
new ArrayList<>(
66-
parseTypeFromArgumentName(
67-
argumentName,
68-
servicePackage,
69-
inputMessage,
70-
messageTypes,
71-
resourceNames,
72-
patternsToResourceNames,
73-
outputArgResourceNames));
63+
List<String> argumentNames = new ArrayList<>();
64+
Map<String, List<MethodArgument>> argumentNameToOverloads = new HashMap<>();
7465

66+
// stringSig.split: ["content", "error"].
67+
for (String argumentName : stringSig.split(METHOD_SIGNATURE_DELIMITER)) {
68+
// For resource names, this will be empty.
69+
List<TypeNode> argumentTypePathAcc = new ArrayList<>();
70+
// There should be more than one type returned only when we encounter a reousrce name.
71+
List<TypeNode> argumentTypes =
72+
parseTypeFromArgumentName(
73+
argumentName,
74+
servicePackage,
75+
inputMessage,
76+
messageTypes,
77+
resourceNames,
78+
patternsToResourceNames,
79+
argumentTypePathAcc,
80+
outputArgResourceNames);
7581
int dotLastIndex = argumentName.lastIndexOf(DOT);
7682
String actualArgumentName =
7783
dotLastIndex < 0 ? argumentName : argumentName.substring(dotLastIndex + 1);
84+
argumentNames.add(actualArgumentName);
85+
argumentNameToOverloads.put(
86+
actualArgumentName,
87+
argumentTypes.stream()
88+
.map(
89+
type ->
90+
MethodArgument.builder()
91+
.setName(actualArgumentName)
92+
.setType(type)
93+
.setIsResourceNameHelper(
94+
argumentTypes.size() > 1 && !type.equals(TypeNode.STRING))
95+
.setNestedTypes(argumentTypePathAcc)
96+
.build())
97+
.collect(Collectors.toList()));
98+
}
99+
signatures.addAll(flattenMethodSignatureVariants(argumentNames, argumentNameToOverloads));
100+
}
101+
return signatures;
102+
}
78103

79-
int typeLastIndex = argumentTypePath.size() - 1;
80-
TypeNode argumentType = argumentTypePath.get(typeLastIndex);
81-
argumentTypePath.remove(typeLastIndex);
104+
@VisibleForTesting
105+
static List<List<MethodArgument>> flattenMethodSignatureVariants(
106+
List<String> argumentNames, Map<String, List<MethodArgument>> argumentNameToOverloads) {
107+
Preconditions.checkState(
108+
argumentNames.size() == argumentNameToOverloads.size(),
109+
String.format(
110+
"Cardinality of argument names %s do not match that of overloaded types %s",
111+
argumentNames, argumentNameToOverloads));
112+
for (String name : argumentNames) {
113+
Preconditions.checkNotNull(
114+
argumentNameToOverloads.get(name),
115+
String.format("No corresponding overload types found for argument %s", name));
116+
}
117+
return flattenMethodSignatureVariants(argumentNames, argumentNameToOverloads, 0);
118+
}
82119

83-
arguments.add(
84-
MethodArgument.builder()
85-
.setName(actualArgumentName)
86-
.setType(argumentType)
87-
.setNestedTypes(argumentTypePath)
88-
.build());
120+
private static List<List<MethodArgument>> flattenMethodSignatureVariants(
121+
List<String> argumentNames,
122+
Map<String, List<MethodArgument>> argumentNameToOverloads,
123+
int depth) {
124+
List<List<MethodArgument>> methodArgs = new ArrayList<>();
125+
if (depth >= argumentNames.size() - 1) {
126+
for (MethodArgument methodArg : argumentNameToOverloads.get(argumentNames.get(depth))) {
127+
methodArgs.add(Lists.newArrayList(methodArg));
89128
}
90-
signatures.add(arguments);
129+
return methodArgs;
91130
}
92-
return signatures;
131+
132+
List<List<MethodArgument>> subsequentArgs =
133+
flattenMethodSignatureVariants(argumentNames, argumentNameToOverloads, depth + 1);
134+
for (MethodArgument methodArg : argumentNameToOverloads.get(argumentNames.get(depth))) {
135+
for (List<MethodArgument> subsequentArg : subsequentArgs) {
136+
// Use a new list to avoid appending all subsequent elements (in upcoming loop iterations)
137+
// to the same list.
138+
List<MethodArgument> appendedArgs = new ArrayList<>(subsequentArg);
139+
appendedArgs.add(0, methodArg);
140+
methodArgs.add(appendedArgs);
141+
}
142+
}
143+
return methodArgs;
93144
}
94145

95146
private static List<TypeNode> parseTypeFromArgumentName(
@@ -99,35 +150,33 @@ private static List<TypeNode> parseTypeFromArgumentName(
99150
Map<String, Message> messageTypes,
100151
Map<String, ResourceName> resourceNames,
101152
Map<String, ResourceName> patternsToResourceNames,
153+
List<TypeNode> argumentTypePathAcc,
102154
Set<ResourceName> outputArgResourceNames) {
103-
return parseTypeFromArgumentName(
104-
argumentName,
105-
servicePackage,
106-
inputMessage,
107-
messageTypes,
108-
resourceNames,
109-
patternsToResourceNames,
110-
outputArgResourceNames,
111-
new ArrayList<>());
112-
}
113155

114-
private static List<TypeNode> parseTypeFromArgumentName(
115-
String argumentName,
116-
String servicePackage,
117-
Message inputMessage,
118-
Map<String, Message> messageTypes,
119-
Map<String, ResourceName> resourceNames,
120-
Map<String, ResourceName> patternsToResourceNames,
121-
Set<ResourceName> outputArgResourceNames,
122-
List<TypeNode> typeAcc) {
123156
int dotIndex = argumentName.indexOf(DOT);
124-
// TODO(miraleung): Fake out resource names here.
125157
if (dotIndex < 1) {
126158
Field field = inputMessage.fieldMap().get(argumentName);
127159
Preconditions.checkNotNull(
128-
field, String.format("Field %s not found, %s", argumentName, inputMessage.fieldMap()));
129-
return Arrays.asList(field.type());
160+
field,
161+
String.format(
162+
"Field %s not found from input message %s values %s",
163+
argumentName, inputMessage.name(), inputMessage.fieldMap().keySet()));
164+
if (!field.hasResourceReference()) {
165+
return Arrays.asList(field.type());
166+
}
167+
168+
// Parse the resource name tyeps.
169+
List<ResourceName> resourceNameArgs =
170+
ResourceReferenceParser.parseResourceNames(
171+
field.resourceReference(), servicePackage, resourceNames, patternsToResourceNames);
172+
outputArgResourceNames.addAll(resourceNameArgs);
173+
List<TypeNode> allFieldTypes = new ArrayList<>();
174+
allFieldTypes.add(TypeNode.STRING);
175+
allFieldTypes.addAll(
176+
resourceNameArgs.stream().map(r -> r.type()).collect(Collectors.toList()));
177+
return allFieldTypes;
130178
}
179+
131180
Preconditions.checkState(
132181
dotIndex < argumentName.length() - 1,
133182
String.format(
@@ -137,16 +186,6 @@ private static List<TypeNode> parseTypeFromArgumentName(
137186

138187
// Must be a sub-message for a type's subfield to be valid.
139188
Field firstField = inputMessage.fieldMap().get(firstFieldName);
140-
if (firstField.hasResourceReference()) {
141-
List<ResourceName> resourceNameArgs =
142-
ResourceReferenceParser.parseResourceNames(
143-
firstField.resourceReference(),
144-
servicePackage,
145-
resourceNames,
146-
patternsToResourceNames);
147-
outputArgResourceNames.addAll(resourceNameArgs);
148-
return resourceNameArgs.stream().map(r -> r.type()).collect(Collectors.toList());
149-
}
150189

151190
Preconditions.checkState(
152191
!firstField.isRepeated(),
@@ -164,17 +203,16 @@ private static List<TypeNode> parseTypeFromArgumentName(
164203
String.format(
165204
"Message type %s for field reference %s invalid", firstFieldTypeName, firstFieldName));
166205

167-
List<TypeNode> newAcc = new ArrayList<>(typeAcc);
168-
newAcc.add(firstFieldType);
206+
argumentTypePathAcc.add(firstFieldType);
169207
return parseTypeFromArgumentName(
170208
remainingArgumentName,
171209
servicePackage,
172210
firstFieldMessage,
173211
messageTypes,
174212
resourceNames,
175213
patternsToResourceNames,
176-
outputArgResourceNames,
177-
newAcc);
214+
argumentTypePathAcc,
215+
outputArgResourceNames);
178216
}
179217

180218
private static Map<String, ResourceName> createPatternResourceNameMap(

src/main/java/com/google/api/generator/gapic/protoparser/ResourceNameParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ private static Optional<ResourceName> createResourceName(
116116
protoResource.getType()));
117117

118118
if (patterns.size() == 1 && patterns.get(0).equals(ResourceNameConstants.WILDCARD_PATTERN)) {
119-
return Optional.empty();
119+
return Optional.of(ResourceName.createWildcard(protoResource.getType(), pakkage));
120120
}
121121

122122
// Assuming that both patterns end with the same variable name.

0 commit comments

Comments
 (0)