private static void putAll(Map<ProtoType, ClassName> wireToJava, String javaPackage, ClassName enclosingClassName, List<Type> types) { for (Type type : types) { ClassName className = enclosingClassName != null ? enclosingClassName.nestedClass(type.type().simpleName()) : ClassName.get(javaPackage, type.type().simpleName()); wireToJava.put(type.type(), className); putAll(wireToJava, javaPackage, className, type.nestedTypes()); } }
private void register(Type type) { protoTypeNames.put(type.type().toString(), type); for (Type nestedType : type.nestedTypes()) { register(nestedType); } }
private static void index(Map<String, Type> typesByName, Type type) { typesByName.put(type.type().toString(), type); for (Type nested : type.nestedTypes()) { index(typesByName, nested); } }
private String resolveContext() { for (int i = contextStack.size() - 1; i >= 0; i--) { Object context = contextStack.get(i); if (context instanceof Type) { return ((Type) context).type().toString(); } else if (context instanceof ProtoFile) { String packageName = ((ProtoFile) context).packageName(); return packageName != null ? packageName : ""; } else if (context instanceof Field && ((Field) context).isExtension()) { String packageName = ((Field) context).packageName(); return packageName != null ? packageName : ""; } } throw new IllegalStateException(); }
/** Returns a standalone adapter for {@code type}. */ public TypeSpec generateAdapterForCustomType(Type type) { NameAllocator nameAllocator = nameAllocators.getUnchecked(type); ClassName adapterTypeName = abstractAdapterName(type.type()); ClassName typeName = (ClassName) typeName(type.type()); TypeSpec.Builder adapter; if (type instanceof MessageType) { adapter = messageAdapter(nameAllocator, (MessageType) type, typeName, adapterTypeName, null) .toBuilder(); } else { adapter = enumAdapter(nameAllocator, (EnumType) type, typeName, adapterTypeName).toBuilder(); } if (adapterTypeName.enclosingClassName() != null) adapter.addModifiers(STATIC); for (Type nestedType : type.nestedTypes()) { if (profile.getAdapter(nestedType.type()) == null) { throw new IllegalArgumentException("Missing custom proto adapter for " + nestedType.type().enclosingTypeOrPackage() + "." + nestedType.type().simpleName() + " when enclosing proto has custom proto adapter."); } adapter.addType(generateAdapterForCustomType(nestedType)); } return adapter.build(); }
/** * Returns a wire adapter for the message or enum type named {@code typeName}. The returned type * adapter doesn't have model classes to encode and decode from, so instead it uses scalar types * ({@linkplain String}, {@linkplain okio.ByteString ByteString}, {@linkplain Integer}, etc.), * {@linkplain Map maps}, and {@linkplain java.util.List lists}. It can both encode and decode * these objects. Map keys are field names. * * @param includeUnknown true to include values for unknown tags in the returned model. Map keys * for such values is the unknown value's tag name as a string. Unknown values are decoded to * {@linkplain Long}, {@linkplain Long}, {@linkplain Integer}, or {@linkplain okio.ByteString * ByteString} for {@linkplain com.squareup.wire.FieldEncoding#VARINT VARINT}, {@linkplain * com.squareup.wire.FieldEncoding#FIXED64 FIXED64}, {@linkplain * com.squareup.wire.FieldEncoding#FIXED32 FIXED32}, or {@linkplain * com.squareup.wire.FieldEncoding#LENGTH_DELIMITED LENGTH_DELIMITED} respectively. */ public ProtoAdapter<Object> protoAdapter(String typeName, boolean includeUnknown) { Type type = getType(typeName); if (type == null) throw new IllegalArgumentException("unexpected type " + typeName); return new SchemaProtoAdapterFactory(this, includeUnknown).get(type.type()); } }
/** Returns the generated code for {@code type}, which may be a top-level or a nested type. */ public TypeSpec generateType(Type type) { AdapterConstant adapterConstant = profile.getAdapter(type.type()); if (adapterConstant != null) { return generateAdapterForCustomType(type); } if (type instanceof MessageType) { //noinspection deprecation: Only deprecated as a public API. return generateMessage((MessageType) type); } if (type instanceof EnumType) { //noinspection deprecation: Only deprecated as a public API. return generateEnum((EnumType) type); } if (type instanceof EnclosingType) { return generateEnclosingType((EnclosingType) type); } throw new IllegalStateException("Unknown type: " + type); }
private void markType(Type type) { markOptions(type.options()); if (marks.containsAllMembers(type.type())) { if (type instanceof MessageType) { markMessage((MessageType) type); } else if (type instanceof EnumType) { markEnum((EnumType) type); } } }
private void markRoots(Type type) { ProtoType protoType = type.type(); if (identifierSet.includes(protoType)) { marks.root(protoType); queue.add(protoType); } else { if (type instanceof MessageType) { for (Field field : ((MessageType) type).fieldsAndOneOfFields()) { markRoots(ProtoMember.get(protoType, field.name())); } } else if (type instanceof EnumType) { for (EnumConstant enumConstant : ((EnumType) type).constants()) { markRoots(ProtoMember.get(protoType, enumConstant.name())); } } else { throw new AssertionError(); } } for (Type nested : type.nestedTypes()) { markRoots(nested); } }
@Test public void linkMessage() throws Exception { Schema schema = new RepoBuilder() .add("message.proto", "" + "import \"foo.proto\";\n" + "message Message {\n" + " optional foo_package.Foo field = 1;\n" + " map<string, foo_package.Bar> bars = 2;\n" + "}\n") .add("foo.proto", "" + "package foo_package;\n" + "message Foo {\n" + "}\n" + "message Bar {\n" + "}\n") .schema(); MessageType message = (MessageType) schema.getType("Message"); Field field = message.field("field"); assertThat(field.type()).isEqualTo(schema.getType("foo_package.Foo").type()); ProtoType bars = message.field("bars").type(); assertThat(bars.keyType()).isEqualTo(ProtoType.STRING); assertThat(bars.valueType()).isEqualTo(schema.getType("foo_package.Bar").type()); }
@Test public void linkService() throws Exception { Schema schema = new RepoBuilder() .add("service.proto", "" + "import \"request.proto\";\n" + "import \"response.proto\";\n" + "service Service {\n" + " rpc Call (Request) returns (Response);\n" + "}\n") .add("request.proto", "" + "message Request {\n" + "}\n") .add("response.proto", "" + "message Response {\n" + "}\n") .schema(); Service service = schema.getService("Service"); Rpc call = service.rpc("Call"); assertThat(call.requestType()).isEqualTo(schema.getType("Request").type()); assertThat(call.responseType()).isEqualTo(schema.getType("Response").type()); }
public void execute() throws IOException { Schema schema = loadSchema(); if (!identifierSet.isEmpty()) { schema = retainRoots(schema); } JavaGenerator javaGenerator = JavaGenerator.get(schema); ServiceGenerator serviceGenerator = new ServiceGenerator(javaGenerator); for (ProtoFile protoFile : schema.protoFiles()) { for (Type type : protoFile.types()) { Stopwatch stopwatch = Stopwatch.createStarted(); TypeSpec typeSpec = javaGenerator.generateType(type); ClassName javaTypeName = (ClassName) javaGenerator.typeName(type.type()); writeJavaFile(javaTypeName, typeSpec, type.location(), stopwatch); } for (Service service : protoFile.services()) { Stopwatch stopwatch = Stopwatch.createStarted(); ClassName javaTypeName = (ClassName) javaGenerator.typeName(service.type()); TypeSpec typeSpec = serviceGenerator.api(service); writeJavaFile(javaTypeName, typeSpec, service.location(), stopwatch); } } }
markField(type.type(), field); continue;
@Ignore("Resolution happens from the root not from inside Outer and so this fails.") @Test public void linkExtendTypeInOuterMessage() throws Exception { Schema schema = new RepoBuilder() .add("foo.proto", "" + "message Other {\n" + " extensions 1;\n" + "}\n" + "message Outer {\n" + " enum Choice {\n" + " ZERO = 0;\n" + " ONE = 1;\n" + " }\n" + "\n" + " extend Other {\n" + " optional Choice choice = 1;\n" + " }\n" + "}") .schema(); MessageType message = (MessageType) schema.getType("Other"); Field field = message.field("choice"); assertThat(field.type()).isEqualTo(schema.getType("Outer.Choice").type()); }
private ProtoType resolveType(String name, boolean messageOnly) { ProtoType type = ProtoType.get(name); if (type.isScalar()) { if (messageOnly) { addError("expected a message but was %s", name); } return type; } if (type.isMap()) { if (messageOnly) { addError("expected a message but was %s", name); } ProtoType keyType = resolveType(type.keyType().toString(), false); ProtoType valueType = resolveType(type.valueType().toString(), false); return new ProtoType(keyType, valueType, name); } Type resolved = resolve(name, protoTypeNames); if (resolved == null) { addError("unable to resolve %s", name); return ProtoType.BYTES; // Just return any placeholder. } if (messageOnly && !(resolved instanceof MessageType)) { addError("expected a message but was %s", name); return ProtoType.BYTES; // Just return any placeholder. } return resolved.type(); }
private static void putAll(Map<ProtoType, ClassName> wireToJava, String javaPackage, ClassName enclosingClassName, List<Type> types) { for (Type type : types) { ClassName className = enclosingClassName != null ? enclosingClassName.nestedClass(type.type().simpleName()) : ClassName.get(javaPackage, type.type().simpleName()); wireToJava.put(type.type(), className); putAll(wireToJava, javaPackage, className, type.nestedTypes()); } }
private static void index(Map<String, Type> typesByName, Type type) { typesByName.put(type.type().toString(), type); for (Type nested : type.nestedTypes()) { index(typesByName, nested); } }
private static void index(Map<String, Type> typesByName, Type type) { typesByName.put(type.type().toString(), type); for (Type nested : type.nestedTypes()) { index(typesByName, nested); } }