Skip to content

Commit b34805e

Browse files
committed
allow option spec name to declare its own parens instead of guessing.
1 parent c281a53 commit b34805e

File tree

2 files changed

+238
-206
lines changed

2 files changed

+238
-206
lines changed

java/protopoet/OptionSpec.java

Lines changed: 107 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727
import java.util.List;
2828

2929
/**
30-
* Models an Option in the Protocol Buffers language.
31-
* Learn more: https://developers.google.com/protocol-buffers/docs/proto#options
30+
* Models an Option in the Protocol Buffers language. Learn more:
31+
* https://developers.google.com/protocol-buffers/docs/proto#options
3232
*/
3333
public final class OptionSpec implements Buildable<OptionSpec>, Emittable {
3434

@@ -71,7 +71,7 @@ public static Builder oneofOption(String optionName) {
7171
public static Builder methodOption(String optionName) {
7272
return builder(OptionType.METHOD, optionName);
7373
}
74-
74+
7575
/** Creates a builder for an {@link OptionSpec}. */
7676
static Builder builder(OptionType optionType, String optionName) {
7777
checkNotNull(optionType, "option type may not be null");
@@ -80,68 +80,69 @@ static Builder builder(OptionType optionType, String optionName) {
8080
}
8181

8282
// Snippet of resuable logic for rendering field-based options.
83-
static ProtoWriter emitFieldOptions(List<OptionSpec> options,
84-
ProtoWriter writer) throws IOException {
83+
static ProtoWriter emitFieldOptions(List<OptionSpec> options, ProtoWriter writer)
84+
throws IOException {
8585
if (!options.isEmpty()) {
8686
writer.emit(" [");
8787
for (int i = 0; i < options.size(); i++) {
8888
options.get(i).emit(writer);
89-
if (i+1 < options.size()) {
89+
if (i + 1 < options.size()) {
9090
writer.emit(", ");
9191
}
9292
}
9393
writer.emit("]");
9494
}
9595
return writer;
9696
}
97-
97+
9898
// Field option types have specialized formatting that are inconsistent with non-field options
9999
// such as Message, Service, File, etc.
100-
private static ImmutableSet<OptionType> FIELD_OPTION_TYPES = ImmutableSet.of(OptionType.FIELD,
101-
OptionType.ENUM_VALUE);
100+
private static ImmutableSet<OptionType> FIELD_OPTION_TYPES =
101+
ImmutableSet.of(OptionType.FIELD, OptionType.ENUM_VALUE);
102102

103103
// Protobufs have some well known option names that require special formatting to
104104
// disambiguate from custom options. This is largely a rendering implementation
105105
// detail so we keep a list sycned with this file:
106106
// https://github.com/google/protobuf/blob/master/src/google/protobuf/descriptor.proto
107107
private static ImmutableMap<OptionType, ImmutableSet<String>> WELL_KNOWN_OPTIONS;
108+
108109
static {
109-
WELL_KNOWN_OPTIONS = ImmutableMap.<OptionType, ImmutableSet<String>>builder()
110-
.put(OptionType.FILE, ImmutableSet.of("java_package",
111-
"java_outer_classname",
112-
"java_multiple_files",
113-
"java_generate_equals_and_hash",
114-
"java_string_check_utf8",
115-
"optimize_for",
116-
"go_package",
117-
"cc_generic_services",
118-
"java_generic_services",
119-
"py_generic_services",
120-
"php_generic_services",
121-
"deprecated",
122-
"cc_enable_arenas",
123-
"objc_class_prefix",
124-
"csharp_namespace",
125-
"swift_prefix",
126-
"php_class_prefix",
127-
"php_namespace"))
128-
.put(OptionType.MESSAGE, ImmutableSet.of("message_set_wire_format",
129-
"no_standard_descriptor_accessor",
130-
"deprecated"))
131-
.put(OptionType.SERVICE, ImmutableSet.of("deprecated"))
132-
.put(OptionType.ENUM, ImmutableSet.of("allow_alias",
133-
"deprecated"))
134-
.put(OptionType.ONEOF, ImmutableSet.of())
135-
.put(OptionType.FIELD, ImmutableSet.of("ctype",
136-
"packed",
137-
"jstype",
138-
"lazy",
139-
"deprecated",
140-
"weak"))
141-
.put(OptionType.ENUM_VALUE, ImmutableSet.of("deprecated"))
142-
.put(OptionType.METHOD, ImmutableSet.of("deprecated",
143-
"idempotency_level"))
144-
.build();
110+
WELL_KNOWN_OPTIONS =
111+
ImmutableMap.<OptionType, ImmutableSet<String>>builder()
112+
.put(
113+
OptionType.FILE,
114+
ImmutableSet.of(
115+
"java_package",
116+
"java_outer_classname",
117+
"java_multiple_files",
118+
"java_generate_equals_and_hash",
119+
"java_string_check_utf8",
120+
"optimize_for",
121+
"go_package",
122+
"cc_generic_services",
123+
"java_generic_services",
124+
"py_generic_services",
125+
"php_generic_services",
126+
"deprecated",
127+
"cc_enable_arenas",
128+
"objc_class_prefix",
129+
"csharp_namespace",
130+
"swift_prefix",
131+
"php_class_prefix",
132+
"php_namespace"))
133+
.put(
134+
OptionType.MESSAGE,
135+
ImmutableSet.of(
136+
"message_set_wire_format", "no_standard_descriptor_accessor", "deprecated"))
137+
.put(OptionType.SERVICE, ImmutableSet.of("deprecated"))
138+
.put(OptionType.ENUM, ImmutableSet.of("allow_alias", "deprecated"))
139+
.put(OptionType.ONEOF, ImmutableSet.of())
140+
.put(
141+
OptionType.FIELD,
142+
ImmutableSet.of("ctype", "packed", "jstype", "lazy", "deprecated", "weak"))
143+
.put(OptionType.ENUM_VALUE, ImmutableSet.of("deprecated"))
144+
.put(OptionType.METHOD, ImmutableSet.of("deprecated", "idempotency_level"))
145+
.build();
145146
}
146147

147148
private final OptionType optionType;
@@ -182,16 +183,13 @@ public void emit(ProtoWriter writer) throws IOException {
182183
// different approach for both field and non-field use cases.
183184
if (optionValueType == FieldType.MESSAGE) {
184185
if (!isFieldOptionType) {
185-
writer
186-
.emit(String.format("option %s = {\n", formattedOptionName))
187-
.indent();
186+
writer.emit(String.format("option %s = {\n", formattedOptionName)).indent();
188187
// Cast is safe here because the builder below enforces type safety.
189188
for (FieldValue fieldValue : (Iterable<FieldValue>) optionValue) {
190-
writer.emit(String.format("%s: %s\n", fieldValue.fieldName(), fieldValue.formattedValue()));
189+
writer.emit(
190+
String.format("%s: %s\n", fieldValue.fieldName(), fieldValue.formattedValue()));
191191
}
192-
writer
193-
.unindent()
194-
.emit("};\n");
192+
writer.unindent().emit("};\n");
195193
return;
196194
}
197195

@@ -214,9 +212,12 @@ OptionType optionType() {
214212
}
215213

216214
private static String formatOptionName(OptionType optionType, String optionName) {
217-
checkState(WELL_KNOWN_OPTIONS.containsKey(optionType),
218-
String.format("unexpected option type: %s", optionType));
219-
return WELL_KNOWN_OPTIONS.get(optionType).contains(optionName) ? optionName : "(" + optionName + ")";
215+
checkState(
216+
WELL_KNOWN_OPTIONS.containsKey(optionType),
217+
String.format("unexpected option type: %s", optionType));
218+
return WELL_KNOWN_OPTIONS.get(optionType).contains(optionName) || optionName.startsWith("(")
219+
? optionName
220+
: "(" + optionName + ")";
220221
}
221222

222223
/** Builder for producing new instances of {@link OptionSpec}. */
@@ -227,72 +228,77 @@ public static final class Builder implements Buildable<OptionSpec> {
227228
private ImmutableList<String> optionComment = ImmutableList.of();
228229
private FieldType optionValueType;
229230
private Object optionValue;
230-
231+
231232
private Builder(OptionType optionType, String optionName) {
232233
this.optionType = optionType;
233234
this.optionName = optionName;
234235
}
235236

236-
/** Declares a top-level comment for the option. Note, this only renders for non-field options. */
237+
/**
238+
* Declares a top-level comment for the option. Note, this only renders for non-field options.
239+
*/
237240
public Builder setOptionComment(Iterable<String> lines) {
238-
checkState(!OptionSpec.FIELD_OPTION_TYPES.contains(optionType),
239-
"comments aren't available for field options");
241+
checkState(
242+
!OptionSpec.FIELD_OPTION_TYPES.contains(optionType),
243+
"comments aren't available for field options");
240244
optionComment = ImmutableList.copyOf(lines);
241245
return this;
242246
}
243247

244-
/** Declares a top-level comment for the option. Note, this only renders for non-field options. */
248+
/**
249+
* Declares a top-level comment for the option. Note, this only renders for non-field options.
250+
*/
245251
public Builder setOptionComment(String... lines) {
246252
return setOptionComment(ImmutableList.copyOf(lines));
247253
}
248254

249255
/** Sets an integer-based value (eg: int32, uint32, fixed32, sfixed32). */
250256
public Builder setValue(FieldType valueType, int intValue) {
251257
switch (valueType) {
252-
case INT32:
253-
case UINT32:
254-
case FIXED32:
255-
case SFIXED32:
256-
optionValueType = valueType;
257-
optionValue = intValue;
258-
return this;
259-
default:
260-
throw new IllegalArgumentException(String.format("'%s' invalid type for an int value",
261-
valueType));
258+
case INT32:
259+
case UINT32:
260+
case FIXED32:
261+
case SFIXED32:
262+
optionValueType = valueType;
263+
optionValue = intValue;
264+
return this;
265+
default:
266+
throw new IllegalArgumentException(
267+
String.format("'%s' invalid type for an int value", valueType));
262268
}
263269
}
264270

265271
/** Sets a long-based value (eg: int64, uint64, fixed64, sfixed64). */
266272
public Builder setValue(FieldType valueType, long longValue) {
267273
switch (valueType) {
268-
case INT64:
269-
case UINT64:
270-
case FIXED64:
271-
case SFIXED64:
272-
optionValueType = valueType;
273-
optionValue = longValue;
274-
return this;
275-
default:
276-
throw new IllegalArgumentException(String.format("'%s' invalid type for a long value",
277-
valueType));
274+
case INT64:
275+
case UINT64:
276+
case FIXED64:
277+
case SFIXED64:
278+
optionValueType = valueType;
279+
optionValue = longValue;
280+
return this;
281+
default:
282+
throw new IllegalArgumentException(
283+
String.format("'%s' invalid type for a long value", valueType));
278284
}
279285
}
280286

281287
/** Sets a float-based value. */
282288
public Builder setValue(FieldType valueType, float floatValue) {
283-
checkArgument(valueType == FieldType.FLOAT,
284-
String.format("'%s' invalid type for a float value",
285-
valueType));
289+
checkArgument(
290+
valueType == FieldType.FLOAT,
291+
String.format("'%s' invalid type for a float value", valueType));
286292
optionValueType = valueType;
287293
optionValue = floatValue;
288294
return this;
289295
}
290296

291297
/** Sets a double-based value. */
292298
public Builder setValue(FieldType valueType, double doubleValue) {
293-
checkArgument(valueType == FieldType.DOUBLE,
294-
String.format("'%s' invalid type for a double value",
295-
valueType));
299+
checkArgument(
300+
valueType == FieldType.DOUBLE,
301+
String.format("'%s' invalid type for a double value", valueType));
296302
optionValueType = valueType;
297303
optionValue = doubleValue;
298304
return this;
@@ -302,32 +308,32 @@ public Builder setValue(FieldType valueType, double doubleValue) {
302308
public Builder setValue(FieldType valueType, String stringValue) {
303309
checkNotNull(stringValue, "value must not be null");
304310
switch (valueType) {
305-
case ENUM:
306-
case STRING:
307-
case BYTES:
308-
optionValueType = valueType;
309-
optionValue = stringValue;
310-
return this;
311-
default:
312-
throw new IllegalArgumentException(String.format("'%s' invalid type for a string value",
313-
valueType));
311+
case ENUM:
312+
case STRING:
313+
case BYTES:
314+
optionValueType = valueType;
315+
optionValue = stringValue;
316+
return this;
317+
default:
318+
throw new IllegalArgumentException(
319+
String.format("'%s' invalid type for a string value", valueType));
314320
}
315321
}
316322

317323
/** Sets a boolean value. */
318324
public Builder setValue(FieldType valueType, boolean boolValue) {
319-
checkArgument(valueType == FieldType.BOOL,
320-
String.format("'%s' invalid type for a bool value",
321-
valueType));
325+
checkArgument(
326+
valueType == FieldType.BOOL,
327+
String.format("'%s' invalid type for a bool value", valueType));
322328
optionValueType = valueType;
323329
optionValue = boolValue;
324330
return this;
325331
}
326332

327333
public Builder setValue(FieldType valueType, Iterable<FieldValue> fieldValues) {
328-
checkArgument(valueType == FieldType.MESSAGE,
329-
String.format("'%s' invalid type for a message value",
330-
valueType));
334+
checkArgument(
335+
valueType == FieldType.MESSAGE,
336+
String.format("'%s' invalid type for a message value", valueType));
331337
optionValueType = valueType;
332338
optionValue = fieldValues;
333339
return this;

0 commit comments

Comments
 (0)