Map<ProtoMember, Object> canonicalizeOption( Linker linker, ProtoType extensionType, OptionElement option) { Type type = linker.get(extensionType); if (!(type instanceof MessageType)) { return null; // No known extensions for the given extension type. } MessageType messageType = (MessageType) type; String[] path; Field field = messageType.field(option.name()); if (field != null) { // This is an option declared by descriptor.proto. path = new String[] {option.name()}; } else { // This is an option declared by an extension. Map<String, Field> extensionsForType = messageType.extensionFieldsMap(); path = resolveFieldPath(option.name(), extensionsForType.keySet()); String packageName = linker.packageName(); if (path == null && packageName != null) { // If the path couldn't be resolved, attempt again by prefixing it with the package name. path = resolveFieldPath(packageName + "." + option.name(), extensionsForType.keySet()); } if (path == null) { return null; // Unable to find the root of this field path. } field = extensionsForType.get(path[0]); } Map<ProtoMember, Object> result = new LinkedHashMap<>(); Map<ProtoMember, Object> last = result; ProtoType lastProtoType = messageType.type(); for (int i = 1; i < path.length; i++) { Map<ProtoMember, Object> nested = new LinkedHashMap<>(); last.put(ProtoMember.get(lastProtoType, field), nested); lastProtoType = field.type(); last = nested; field = linker.dereference(field, path[i]); if (field == null) { return null; // Unable to dereference this path segment. } } last.put( ProtoMember.get(lastProtoType, field), canonicalizeValue(linker, field, option.value())); return result; }