private MethodSpec newBuilder(NameAllocator nameAllocator, MessageType message) { NameAllocator localNameAllocator = nameAllocator.clone(); String builderName = localNameAllocator.newName("builder"); ClassName javaType = (ClassName) typeName(message.type()); ClassName builderJavaType = javaType.nestedClass("Builder"); MethodSpec.Builder result = MethodSpec.methodBuilder("newBuilder") .addAnnotation(Override.class) .addModifiers(PUBLIC) .returns(builderJavaType) .addStatement("$1T $2L = new $1T()", builderJavaType, builderName); List<Field> fields = message.fieldsAndOneOfFields(); for (Field field : fields) { String fieldName = localNameAllocator.get(field); if (field.isRepeated() || field.type().isMap()) { result.addStatement("$1L.$2L = $3T.copyOf($2S, $2L)", builderName, fieldName, Internal.class); } else { result.addStatement("$1L.$2L = $2L", builderName, fieldName); } } result.addStatement("$L.addUnknownFields(unknownFields())", builderName); result.addStatement("return $L", builderName); return result.build(); }
public Field getField(ProtoMember protoMember) { Type type = getType(protoMember.type()); if (!(type instanceof MessageType)) return null; Field field = ((MessageType) type).field(protoMember.member()); if (field == null) { field = ((MessageType) type).extensionField(protoMember.member()); } return field; }
/** Returns the field named {@code field} on the message type of {@code self}. */ Field dereference(Field self, String field) { if (field.startsWith("[") && field.endsWith("]")) { field = field.substring(1, field.length() - 1); } Type type = protoTypeNames.get(self.type().toString()); if (type instanceof MessageType) { MessageType messageType = (MessageType) type; Field messageField = messageType.field(field); if (messageField != null) return messageField; Map<String, Field> typeExtensions = messageType.extensionFieldsMap(); Field extensionField = resolve(field, typeExtensions); if (extensionField != null) return extensionField; } return null; // Unable to traverse this field path. }
ClassName javaType = (ClassName) typeName(type.type()); ClassName builderJavaType = javaType.nestedClass("Builder"); if (!type.documentation().isEmpty()) { builder.addJavadoc("$L\n", sanitizeJavadoc(type.documentation())); MESSAGE_OPTIONS, nameAllocator.get("MESSAGE_OPTIONS"), type.options()); if (messageOptions != null) { builder.addField(messageOptions); for (Field field : type.fieldsAndOneOfFields()) { String fieldName = nameAllocator.get(field); String optionsFieldName = "FIELD_OPTIONS_" + fieldName.toUpperCase(Locale.US); for (Field field : type.fieldsAndOneOfFields()) { TypeName fieldJavaType = fieldType(field); for (Type nestedType : type.nestedTypes()) { builder.addType(generateType(nestedType));
private TypeSpec builder(NameAllocator nameAllocator, MessageType type, ClassName javaType, ClassName builderType) { TypeSpec.Builder result = TypeSpec.classBuilder("Builder") .addModifiers(PUBLIC, STATIC, FINAL); result.superclass(builderOf(javaType, builderType)); for (Field field : type.fieldsAndOneOfFields()) { String fieldName = nameAllocator.get(field); result.addField(fieldType(field), fieldName, PUBLIC); } result.addMethod(builderNoArgsConstructor(nameAllocator, type)); for (Field field : type.fields()) { result.addMethod(setter(nameAllocator, builderType, null, field)); } for (OneOf oneOf : type.oneOfs()) { for (Field field : oneOf.fields()) { result.addMethod(setter(nameAllocator, builderType, oneOf, field)); } } result.addMethod(builderBuild(nameAllocator, type, javaType)); return result.build(); }
Field field = messageType.field(option.name()); if (field != null) { } else { Map<String, Field> extensionsForType = messageType.extensionFieldsMap(); ProtoType lastProtoType = messageType.type(); for (int i = 1; i < path.length; i++) { Map<ProtoMember, Object> nested = new LinkedHashMap<>();
public ImmutableList<Field> getRequiredFields() { ImmutableList.Builder<Field> required = ImmutableList.builder(); for (Field field : fieldsAndOneOfFields()) { if (field.isRequired()) { required.add(field); } } return required.build(); }
.addStatement("super($N, $N)", adapterName, unknownFieldsName); for (OneOf oneOf : type.oneOfs()) { if (oneOf.fields().size() < 2) continue; CodeBlock.Builder fieldNamesBuilder = CodeBlock.builder(); result.endControlFlow(); for (Field field : type.fieldsAndOneOfFields()) { TypeName javaType = fieldType(field); String fieldName = localNameAllocator.get(field);
@Test public void fieldTypeImported() throws Exception { Schema schema = new RepoBuilder() .add("a.proto", "" + "package pa;\n" + "import \"b.proto\";\n" + "message A {\n" + " optional pb.B b = 1;\n" + "}\n") .add("b.proto", "" + "package pb;\n" + "message B {\n" + "}\n") .schema(); MessageType a = (MessageType) schema.getType("pa.A"); MessageType b = (MessageType) schema.getType("pb.B"); assertThat(a.field("b").type()).isEqualTo(b.type()); }
@Test public void scalarFieldIsPacked() throws Exception { Schema schema = new RepoBuilder() .add("message.proto", "" + "message Message {\n" + " repeated int32 a = 1;\n" + " repeated int32 b = 2 [packed=false];\n" + " repeated int32 c = 3 [packed=true];\n" + "}\n") .schema(); MessageType message = (MessageType) schema.getType("Message"); assertThat(message.field("a").isPacked()).isFalse(); assertThat(message.field("b").isPacked()).isFalse(); assertThat(message.field("c").isPacked()).isTrue(); }
/** * Decides if a constructor should take all fields or a builder as a parameter. */ private boolean constructorTakesAllFields(MessageType type) { return type.fields().size() < MAX_PARAMS_IN_CONSTRUCTOR; }
@Test public void retainFieldRetainsOneOf() throws Exception { Schema schema = new RepoBuilder() .add("service.proto", "" + "message Message {\n" + " oneof selection {\n" + " string a = 1;\n" + " string b = 2;\n" + " }\n" + " optional string c = 3;\n" + "}\n") .schema(); Schema pruned = schema.prune(new IdentifierSet.Builder() .include("Message#b") .build()); MessageType message = (MessageType) pruned.getType("Message"); OneOf onlyOneOf = getOnlyElement(message.oneOfs()); assertThat(onlyOneOf.name()).isEqualTo("selection"); assertThat(getOnlyElement(onlyOneOf.fields()).name()).isEqualTo("b"); assertThat(message.field("a")).isNull(); assertThat(message.field("c")).isNull(); }
@Test public void rpcTypeImported() throws Exception { Schema schema = new RepoBuilder() .add("a.proto", "" + "package pa;\n" + "import \"b.proto\";\n" + "service Service {\n" + " rpc Call (pb.B) returns (pb.B);\n" + "}\n") .add("b.proto", "" + "package pb;\n" + "message B {\n" + "}\n") .schema(); Service service = schema.getService("pa.Service"); MessageType b = (MessageType) schema.getType("pb.B"); assertThat(service.rpcs().get(0).requestType()).isEqualTo(b.type()); assertThat(service.rpcs().get(0).responseType()).isEqualTo(b.type()); }
.returns(javaType); List<Field> requiredFields = message.getRequiredFields(); if (!requiredFields.isEmpty()) { CodeBlock.Builder conditionals = CodeBlock.builder().add("$["); for (Field field : message.fieldsAndOneOfFields()) { result.addCode("$L, ", nameAllocator.get(field));
@Override Type retainAll(Schema schema, MarkSet markSet) { ImmutableList.Builder<Type> retainedNestedTypesBuilder = ImmutableList.builder(); for (Type nestedType : nestedTypes) { Type retainedNestedType = nestedType.retainAll(schema, markSet); if (retainedNestedType != null) { retainedNestedTypesBuilder.add(retainedNestedType); } } ImmutableList<Type> retainedNestedTypes = retainedNestedTypesBuilder.build(); if (!markSet.contains(protoType)) { // If this type is not retained, and none of its nested types are retained, prune it. if (retainedNestedTypes.isEmpty()) { return null; } // If this type is not retained but retained nested types, replace it with an enclosing type. return new EnclosingType(location, protoType, documentation, retainedNestedTypes); } ImmutableList.Builder<OneOf> retainedOneOfsBuilder = ImmutableList.builder(); for (OneOf oneOf : oneOfs) { OneOf retainedOneOf = oneOf.retainAll(schema, markSet, protoType); if (retainedOneOf != null) { retainedOneOfsBuilder.add(retainedOneOf); } } ImmutableList<OneOf> retainedOneOfs = retainedOneOfsBuilder.build(); return new MessageType(protoType, location, documentation, name, Field.retainAll(schema, markSet, protoType, declaredFields), Field.retainAll(schema, markSet, protoType, extensionFields), retainedOneOfs, retainedNestedTypes, extensionsList, reserveds, options.retainAll(schema, markSet)); }
@Test public void retainFieldPrunesOneOf() throws Exception { Schema schema = new RepoBuilder() .add("service.proto", "" + "message Message {\n" + " oneof selection {\n" + " string a = 1;\n" + " string b = 2;\n" + " }\n" + " optional string c = 3;\n" + "}\n") .schema(); Schema pruned = schema.prune(new IdentifierSet.Builder() .include("Message#c") .build()); assertThat(((MessageType) pruned.getType("Message")).oneOfs()).isEmpty(); }
@Test public void excludeRepeatedOptions() throws Exception { Schema schema = new RepoBuilder() .add("service.proto", "" + "import \"google/protobuf/descriptor.proto\";\n" + "extend google.protobuf.MessageOptions {\n" + " repeated string a = 22001;\n" + " repeated string b = 22002;\n" + "}\n" + "message Message {\n" + " option (a) = \"a1\";\n" + " option (a) = \"a2\";\n" + " option (b) = \"b1\";\n" + " option (b) = \"b2\";\n" + " optional string f = 1;\n" + "}\n") .schema(); Schema pruned = schema.prune(new IdentifierSet.Builder() .exclude("google.protobuf.MessageOptions#a") .build()); MessageType message = (MessageType) pruned.getType("Message"); assertThat(message.options().get(ProtoMember.get(MESSAGE_OPTIONS, "a"))).isNull(); assertThat(message.options().get(ProtoMember.get(MESSAGE_OPTIONS, "b"))) .isEqualTo(ImmutableList.of("b1", "b2")); }
void link(Linker linker) { linker = linker.withContext(this); protoType = linker.resolveMessageType(name); Type type = linker.get(protoType); if (type != null) { ((MessageType) type).addExtensionFields(fields); } }