servo/components/script/dom/bindings/codegen/GlobalGen.py

147 lines
5 KiB
Python

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
# We do one global pass over all the WebIDL to generate our prototype enum
# and generate information for subsequent phases.
import sys
import os
import json
sys.path.append(os.path.join(".", "parser"))
sys.path.append(os.path.join(".", "ply"))
import WebIDL
import cPickle
from Configuration import Configuration
from CodegenRust import GlobalGenRoots, replaceFileIfChanged
def generate_file(config, name, filename):
root = getattr(GlobalGenRoots, name)(config)
code = root.define()
if replaceFileIfChanged(filename, code):
print "Generating %s" % (filename)
else:
print "%s hasn't changed - not touching it" % (filename)
def main():
# Parse arguments.
from optparse import OptionParser
usageString = "usage: %prog [options] configFile outputdir webidldir cssProperties.json [files]"
o = OptionParser(usage=usageString)
o.add_option("--cachedir", dest='cachedir', default=None,
help="Directory in which to cache lex/parse tables.")
o.add_option("--only-html", dest='only_html', action="store_true",
help="Only generate HTML from WebIDL inputs")
o.add_option("--filelist", dest='filelist', default=None,
help="A file containing the list (one per line) of webidl files to process.")
(options, args) = o.parse_args()
if len(args) < 2:
o.error(usageString)
configFile = args[0]
outputdir = args[1]
baseDir = args[2]
css_properties_json = args[3]
if options.filelist is not None:
fileList = [l.strip() for l in open(options.filelist).xreadlines()]
else:
fileList = args[3:]
# Parse the WebIDL.
parser = WebIDL.Parser(options.cachedir)
for filename in fileList:
fullPath = os.path.normpath(os.path.join(baseDir, filename))
with open(fullPath, 'rb') as f:
lines = f.readlines()
parser.parse(''.join(lines), fullPath)
add_css_properties_attributes(fileList, css_properties_json, parser)
parserResults = parser.finish()
if not options.only_html:
# Write the parser results out to a pickle.
resultsPath = os.path.join(outputdir, 'ParserResults.pkl')
with open(resultsPath, 'wb') as resultsFile:
cPickle.dump(parserResults, resultsFile, -1)
# Load the configuration.
config = Configuration(configFile, parserResults)
to_generate = [
('SupportedDomApis', 'apis.html'),
]
if not options.only_html:
to_generate = [
('PrototypeList', 'PrototypeList.rs'),
('RegisterBindings', 'RegisterBindings.rs'),
('InterfaceObjectMap', 'InterfaceObjectMap.rs'),
('InterfaceObjectMapData', 'InterfaceObjectMapData.json'),
('InterfaceTypes', 'InterfaceTypes.rs'),
('InheritTypes', 'InheritTypes.rs'),
('Bindings', os.path.join('Bindings', 'mod.rs')),
('UnionTypes', 'UnionTypes.rs'),
]
for name, filename in to_generate:
generate_file(config, name, os.path.join(outputdir, filename))
def add_css_properties_attributes(webidl_files, css_properties_json, parser):
for filename in webidl_files:
if os.path.basename(filename) == "CSSStyleDeclaration.webidl":
break
else:
return
css_properties = json.load(open(css_properties_json, "rb"))
idl = "partial interface CSSStyleDeclaration {\n%s\n};\n" % "\n".join(
" [%sCEReactions, SetterThrows] attribute [TreatNullAs=EmptyString] DOMString %s;" % (
('Pref="%s", ' % pref if pref else ""),
attribute_name
)
for (property_name, pref) in css_properties
for attribute_name in attribute_names(property_name)
)
parser.parse(idl.encode("utf-8"), "CSSStyleDeclaration_generated.webidl")
def attribute_names(property_name):
# https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-dashed-attribute
if property_name != "float":
yield property_name
else:
yield "_float"
# https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-camel-cased-attribute
if "-" in property_name:
yield "".join(camel_case(property_name))
# https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-webkit-cased-attribute
if property_name.startswith("-webkit-"):
yield "".join(camel_case(property_name), True)
# https://drafts.csswg.org/cssom/#css-property-to-idl-attribute
def camel_case(chars, webkit_prefixed=False):
if webkit_prefixed:
chars = chars[1:]
next_is_uppercase = False
for c in chars:
if c == '-':
next_is_uppercase = True
elif next_is_uppercase:
next_is_uppercase = False
# Should be ASCII-uppercase, but all non-custom CSS property names are within ASCII
yield c.upper()
else:
yield c
if __name__ == '__main__':
main()