def generate_code(request, response):
    """
    Core function. Starts from a CodeGeneratorRequest and adds files to
    a CodeGeneratorResponse
    """
    for proto_file in request.proto_file:
        types = []
        messages = {}

        results = traverse(proto_file)
        map_types = {}
        def full_name(package, item):
            return "%s.%s" % (package, item.name)
        for item, package in results["types"]:
            if item.options.has_key("map_entry"):
                map_types[full_name(package, item)] = dict([(x.name,x) for x in item.field])
        for item, package in results["types"]:
            name = full_name(package, item)
            if name in map_types:
                continue
            data = {
                'name': simplify_name(name),
                'doc': item.comment
            }

            if item.kind == DescriptorProto:
                data.update({
                    'type': 'message',
                    'fields': []
                })
                for f in item.field:
                    kind = type_to_string(f, map_types)
                    data["fields"].append({
                        'name': f.name,
                        'type': kind,
                        'doc': f.comment
                        })
                if len(item.oneof_decl) > 0:
                    data["fields"] = [
                        {
                            "name": item.oneof_decl[0].name,
                            "type": [" %s "% x["type"] for x in data["fields"]],
                            "doc": "\n".join(["%s: %s"%(x["type"],x["doc"]) for x in data["fields"] if x["doc"] != ""])
                        }]
                types.append(data)
            elif item.kind == EnumDescriptorProto:
                comments = ["\n* `%s`: %s"%(v.name, v.comment) for v in item.value]
                data.update({
                    'type': 'enum',
                    'symbols': [v.name for v in item.value]
                })
                data["doc"] += "\n" + " ".join(comments)
                types.append(data)
            elif item.kind == ServiceDescriptorProto:
                for m in item.method:
                    messages[m.name] = {
                        "doc": m.comment,
                        "request": [{
                            "name": "request",
                            "type": ":protobuf:message:`%s`" % simplify_name(m.input_type),
                        }],
                        "response": ":protobuf:message:`%s`" % simplify_name(m.output_type),
                        "errors" : [ ":protobuf:message:`GAException`" ]
                    }
            else:
                raise Exception, item.kind

        comments = "\n".join(results["file"])
        output = {
            "types": types,
            "messages": messages,
            "protocol": proto_file.name.split("/")[-1].split(".")[0],
            'doc': comments,
            "namespace": proto_file.package,
        }

        # Fill response
        f = response.file.add()
        f.name = proto_file.name + '.json'
        f.content = json.dumps(output, indent=2)
Core function. Starts from a CodeGeneratorRequest and adds files to
    a CodeGeneratorResponse