private AnnotationSpec wireFieldAnnotation(Field field) { AnnotationSpec.Builder result = AnnotationSpec.builder(WireField.class); int tag = field.tag(); result.addMember("tag", String.valueOf(tag)); if (field.type().isMap()) { result.addMember("keyAdapter", "$S", adapterString(field.type().keyType())); result.addMember("adapter", "$S", adapterString(field.type().valueType())); } else { result.addMember("adapter", "$S", adapterString(field.type())); } if (!field.isOptional()) { if (field.isPacked()) { result.addMember("label", "$T.PACKED", WireField.Label.class); } else if (field.label() != null) { result.addMember("label", "$T.$L", WireField.Label.class, field.label()); } } if (field.isRedacted()) { result.addMember("redacted", "true"); } return result.build(); }
private MethodSpec messageToString(NameAllocator nameAllocator, MessageType type) { NameAllocator localNameAllocator = nameAllocator.clone(); MethodSpec.Builder result = MethodSpec.methodBuilder("toString") .addAnnotation(Override.class) .addModifiers(PUBLIC) .returns(String.class); String builderName = localNameAllocator.newName("builder"); result.addStatement("$1T $2N = new $1T()", StringBuilder.class, builderName); for (Field field : type.fieldsAndOneOfFields()) { String fieldName = nameAllocator.get(field); if (field.isRepeated() || field.type().isMap()) { result.addCode("if (!$N.isEmpty()) ", fieldName); } else if (!field.isRequired()) { result.addCode("if ($N != null) ", fieldName); } if (field.isRedacted()) { result.addStatement("$N.append(\", $N=██\")", builderName, field.name()); } else { result.addStatement("$N.append(\", $N=\").append($L)", builderName, field.name(), fieldName); } } result.addStatement("return builder.replace(0, 2, \"$L{\").append('}').toString()", type.type().simpleName()); return result.build(); }
public static ProtoMember get(ProtoType type, Field field) { String member = field.isExtension() ? field.qualifiedName() : field.name(); return new ProtoMember(type, member); }
void validate(Linker linker) { linker = linker.withContext(this); if (isPacked() && !isPackable(linker, type)) { linker.addError("packed=true not permitted on %s", type); } if (extension && isRequired()) { linker.addError("extension fields cannot be required", type); } linker.validateImport(location(), type); }
private CodeBlock defaultValue(Field field) { Object defaultValue = field.getDefault(); if (defaultValue == null && isEnum(field.type())) { defaultValue = enumDefault(field.type()).name(); } if (field.type().isScalar() || defaultValue != null) { return fieldInitializer(field.type(), defaultValue); } throw new IllegalStateException("Field " + field + " cannot have default value"); }
String fieldName = nameAllocator.get(field); String optionsFieldName = "FIELD_OPTIONS_" + fieldName.toUpperCase(Locale.US); FieldSpec fieldOptions = optionsField(FIELD_OPTIONS, optionsFieldName, field.options()); if (fieldOptions != null) { builder.addField(fieldOptions); TypeName fieldJavaType = fieldType(field); if ((field.type().isScalar() || isEnum(field.type())) && !field.isRepeated() && !field.isPacked()) { builder.addField(defaultField(nameAllocator, field, fieldJavaType)); FieldSpec.Builder fieldBuilder = FieldSpec.builder(fieldJavaType, fieldName, PUBLIC, FINAL); fieldBuilder.addAnnotation(wireFieldAnnotation(field)); if (!field.documentation().isEmpty()) { fieldBuilder.addJavadoc("$L\n", sanitizeJavadoc(field.documentation())); if (field.isExtension()) { fieldBuilder.addJavadoc("Extension source: $L\n", field.location().withPathOnly()); if (field.isDeprecated()) { fieldBuilder.addAnnotation(Deprecated.class); if (emitAndroidAnnotations && field.isOptional()) { fieldBuilder.addAnnotation(NULLABLE);
public ProtoAdapter<Object> get(ProtoType protoType) { if (protoType.isMap()) throw new UnsupportedOperationException("map types not supported"); ProtoAdapter<?> result = adapterMap.get(protoType); if (result != null) { return (ProtoAdapter<Object>) result; } Type type = schema.getType(protoType); if (type == null) { throw new IllegalArgumentException("unknown type: " + protoType); } if (type instanceof EnumType) { EnumAdapter enumAdapter = new EnumAdapter((EnumType) type); adapterMap.put(protoType, enumAdapter); return enumAdapter; } if (type instanceof MessageType) { MessageAdapter messageAdapter = new MessageAdapter(includeUnknown); // Put the adapter in the map early to mitigate the recursive calls to get() made below. adapterMap.put(protoType, messageAdapter); for (com.squareup.wire.schema.Field field : ((MessageType) type).fields()) { Field fieldAdapter = new Field( field.name(), field.tag(), field.isRepeated(), get(field.type())); messageAdapter.fieldsByName.put(field.name(), fieldAdapter); messageAdapter.fieldsByTag.put(field.tag(), fieldAdapter); } return (ProtoAdapter) messageAdapter; } throw new IllegalArgumentException("unexpected type: " + protoType); }
Multimap<String, Field> nameToField = LinkedHashMultimap.create(); for (Field field : fields) { int tag = field.tag(); if (!Util.isValidTag(tag)) { withContext(field).addError("tag is out of range: %s", tag); withContext(field).addError("tag %s is reserved (%s)", tag, reserved.location()); if (reserved.matchesName(field.name())) { withContext(field).addError("name '%s' is reserved (%s)", field.name(), reserved.location()); nameToField.put(field.qualifiedName(), field); for (Field field : entry.getValue()) { error.append(String.format("\n %s. %s (%s)", index++, field.name(), field.location())); Field first = collidingFields.iterator().next(); StringBuilder error = new StringBuilder(); error.append(String.format("multiple fields share name %s:", first.name())); int index = 1; for (Field field : collidingFields) { error.append(String.format("\n %s. %s (%s)", index++, field.name(), field.location()));
private MethodSpec messageHashCode(NameAllocator nameAllocator, MessageType type) { NameAllocator localNameAllocator = nameAllocator.clone(); String resultName = localNameAllocator.newName("result"); MethodSpec.Builder result = MethodSpec.methodBuilder("hashCode") .addAnnotation(Override.class) .addModifiers(PUBLIC) .returns(int.class); List<Field> fields = type.fieldsAndOneOfFields(); if (fields.isEmpty()) { result.addStatement("return unknownFields().hashCode()"); return result.build(); } result.addStatement("int $N = super.hashCode", resultName); result.beginControlFlow("if ($N == 0)", resultName); result.addStatement("$N = unknownFields().hashCode()", resultName); for (Field field : fields) { String fieldName = localNameAllocator.get(field); result.addCode("$1N = $1N * 37 + ", resultName); if (field.isRepeated() || field.isRequired() || field.type().isMap()) { result.addStatement("$L.hashCode()", fieldName); } else { result.addStatement("($1L != null ? $1L.hashCode() : 0)", fieldName); } } result.addStatement("super.hashCode = $N", resultName); result.endControlFlow(); result.addStatement("return $N", resultName); return result.build(); }
private MethodSpec messageAdapterEncode(NameAllocator nameAllocator, MessageType type, TypeName javaType) { MethodSpec.Builder result = MethodSpec.methodBuilder("encode") .addAnnotation(Override.class) .addModifiers(PUBLIC) .addParameter(ProtoWriter.class, "writer") .addParameter(javaType, "value") .addException(IOException.class); for (Field field : type.fieldsAndOneOfFields()) { int fieldTag = field.tag(); String fieldName = nameAllocator.get(field); CodeBlock adapter = adapterFor(field); if (!field.isRequired() && !field.isRepeated() && !field.type().isMap()) { result.addCode("if (value.$L != null) ", fieldName); } result.addStatement("$L.encodeWithTag(writer, $L, value.$L)", adapter, fieldTag, fieldName); } result.addStatement("writer.writeBytes(value.unknownFields())"); return result.build(); }
String fieldName = nameAllocator.get(field); String optionsFieldName = "FIELD_OPTIONS_" + fieldName.toUpperCase(Locale.US); FieldSpec fieldOptions = optionsField(FIELD_OPTIONS, optionsFieldName, field.options()); if (fieldOptions != null) { builder.addField(fieldOptions); fieldBuilder.addAnnotation(jsonPropertyAnnotation(field)); if (!field.documentation().isEmpty()) { fieldBuilder.addJavadoc("$L\n", sanitizeJavadoc(field.documentation())); if (field.isExtension()) { fieldBuilder.addJavadoc("Extension source: $L\n", field.location().withPathOnly()); if (field.isDeprecated()) { fieldBuilder.addAnnotation(Deprecated.class); if (emitAndroid && field.isOptional()) { fieldBuilder.addAnnotation(NULLABLE);
/** Returns the initial value of {@code field}, or null if it is doesn't have one. */ private @Nullable CodeBlock initialValue(Field field) { if (field.isPacked() || field.isRepeated()) { return CodeBlock.of("$T.newMutableList()", Internal.class); } else if (field.type().isMap()) { return CodeBlock.of("$T.newMutableMap()", Internal.class); } else { return null; } }
private MethodSpec setter( NameAllocator nameAllocator, TypeName builderType, OneOf oneOf, Field field) { TypeName javaType = fieldType(field); String fieldName = nameAllocator.get(field); MethodSpec.Builder result = MethodSpec.methodBuilder(fieldName) .addModifiers(PUBLIC) .addParameter(javaType, fieldName) .returns(builderType); if (!field.documentation().isEmpty()) { result.addJavadoc("$L\n", sanitizeJavadoc(field.documentation())); } if (field.isDeprecated()) { result.addAnnotation(Deprecated.class); } if (field.isRepeated() || field.type().isMap()) { result.addStatement("$T.checkElementsNotNull($L)", Internal.class, fieldName); } result.addStatement("this.$L = $L", fieldName, fieldName); if (oneOf != null) { for (Field other : oneOf.fields()) { if (field != other) { result.addStatement("this.$L = null", nameAllocator.get(other)); } } } result.addStatement("return this"); return result.build(); }
void linkOptions(Linker linker) { linker = linker.withContext(this); options.link(linker); deprecated = options().get(DEPRECATED); packed = options().get(PACKED); // We allow any package name to be used as long as it ends with '.redacted'. redacted = options().optionMatches(".*\\.redacted", "true"); }
private TypeName fieldType(Field field) { ProtoType type = field.type(); if (type.isMap()) { return ParameterizedTypeName.get(ClassName.get(Map.class), typeName(type.keyType()), typeName(type.valueType())); } TypeName messageType = typeName(type); return field.isRepeated() ? listOf(messageType) : messageType; }
/** 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. }