blob: 2ab803f30707821405d12bc09fbc027fbffcd7ea [file] [log] [blame]
#!/usr/bin/python
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import sys
import string
import json
package = sys.argv[1]
output_cc_path = sys.argv[2]
output_h_path = sys.argv[3]
blink_protocol_path = sys.argv[4]
template_h = string.Template("""\
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ${PACKAGE}_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_CONSTANTS_H_
#define ${PACKAGE}_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_CONSTANTS_H_
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// Generated by
// chrome/browser/devtools/devtools_protocol_constants_generator.py from
// gen/blink/core/inspector/protocol.json
#include <string>
namespace $package {
namespace devtools {
extern const char kProtocolVersion[];
bool IsSupportedProtocolVersion(const std::string& version);
extern const char kResult[];
$contents
} // devtools
} // $package
#endif // ${PACKAGE}_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_CONSTANTS_H_
""")
template_cc = string.Template("""\
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// Generated by
// chrome/browser/devtools/devtools_protocol_constants_generator.py from
// gen/blink/core/inspector/protocol.json
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "$package/browser/devtools/devtools_protocol_constants.h"
namespace $package {
namespace devtools {
const char kProtocolVersion[] = "$major.$minor";
bool IsSupportedProtocolVersion(const std::string& version) {
std::vector<base::StringPiece> tokens = base::SplitStringPiece(
version, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
int major, minor;
return tokens.size() == 2 &&
base::StringToInt(tokens[0], &major) && major == $major &&
base::StringToInt(tokens[1], &minor) && minor <= $minor;
}
const char kResult[] = "result";
$contents
} // devtools
} // $package
""")
def Capitalize(s):
return s[:1].capitalize() + s[1:]
def ToIdentifier(s):
return "".join([Capitalize(part) for part in s.split("-")])
references = []
def CreateNamespace(domain_name, data, keys, prefixes, name = None):
result = {}
if name:
result["kName"] = name
for i, key in enumerate(keys):
if key in data:
for parameter in data[key]:
parameter_name = parameter["name"];
result[prefixes[i] + Capitalize(parameter_name)] = parameter_name
if "enum" in parameter:
enum_name = Capitalize(parameter_name)
result[enum_name] = {}
for enum in parameter["enum"]:
result[enum_name]["kEnum" + ToIdentifier(enum)] = enum
reference = ""
if "$ref" in parameter:
reference = parameter["$ref"]
if "items" in parameter and "$ref" in parameter["items"]:
reference = parameter["items"]["$ref"]
if reference:
if not "." in reference:
reference = domain_name + "." + reference
references.append(reference)
return result
def FormatContents(tree, indent, format_string):
outer = dict((key, value) for key, value in tree.iteritems()
if not isinstance(value, dict))
inner = dict((key, value) for key, value in tree.iteritems()
if isinstance(value, dict))
body = ""
body += "".join(indent + format_string.format(key, value)
for (key, value) in sorted(outer.items()))
body += "".join(FormatNamespace(key, value, indent, format_string)
for (key, value) in sorted(inner.items()))
return body
def FormatNamespace(title, tree, indent, format_string):
if (not tree):
return ""
body = '\n' + indent + "namespace " + title + " {\n"
body += FormatContents(tree, indent + " ", format_string)
body += indent + "} // " + title + "\n"
return body
def CreateHeader(tree, output_file):
contents = FormatContents(tree, "", "extern const char {0}[];\n")
output_file.write(template_h.substitute({
"contents": contents,
"package": package,
"PACKAGE": package.upper()
}))
def CreateBody(tree, version, output_file):
contents = FormatContents(tree, "", "const char {0}[] = \"{1}\";\n")
output_file.write(template_cc.substitute({
"major": version["major"],
"minor": version["minor"],
"contents": contents,
"package": package
}))
blink_protocol_data = open(blink_protocol_path).read()
blink_protocol = json.loads(blink_protocol_data)
blink_version = blink_protocol["version"]
domains = blink_protocol["domains"]
namespace_tree = {}
for domain in domains:
domain_value = {}
domain_namespace_name = Capitalize(domain["domain"])
if "commands" in domain:
for command in domain["commands"]:
domain_value[command["name"]] = CreateNamespace(domain["domain"],
command, ["parameters", "returns"], ["kParam", "kResponse"],
domain_namespace_name + "." + command["name"])
if "events" in domain:
for event in domain["events"]:
domain_value[event["name"]] = CreateNamespace(domain["domain"],
event, ["parameters"], ["kParam"],
domain_namespace_name + "." + event["name"])
if domain_value:
namespace_tree[domain_namespace_name] = domain_value
while (references):
reference = references.pop();
path = reference.split(".");
parent_namespace = namespace_tree;
for path_segment in path[0:-1]:
if path_segment not in parent_namespace:
parent_namespace[path_segment] = {}
parent_namespace = parent_namespace[path_segment]
if (path[-1] not in parent_namespace):
try:
domain = [d for d in domains if d["domain"] == path[0]][0]
ref_type = [t for t in domain["types"] if t["id"] == path[1]][0]
parent_namespace[ref_type["id"]] = CreateNamespace(path[0],
ref_type, ["properties"], ["kParam"])
except IndexError:
sys.stderr.write("Failed to resolve type [{0}].\n".format(reference))
sys.exit(1)
for (namespace_name, namespace) in namespace_tree.items():
namespace["kName"] = namespace_name
with open(output_cc_path, "w") as f:
CreateBody(namespace_tree, blink_version, f)
with open(output_h_path, "w") as f:
CreateHeader(namespace_tree, f)