Merge pull request #398 from elemoine/nestedoptions
Support nested options objects
This commit is contained in:
+56
-5
@@ -33,13 +33,52 @@ class Exportable(object):
|
|||||||
|
|
||||||
class Class(Exportable):
|
class Class(Exportable):
|
||||||
|
|
||||||
def __init__(self, name, object_literal):
|
def __init__(self, name, object_literal, objects):
|
||||||
Exportable.__init__(self, name)
|
Exportable.__init__(self, name)
|
||||||
self.object_literal = object_literal
|
self.object_literal = object_literal
|
||||||
|
self.objects = objects
|
||||||
self.props = set()
|
self.props = set()
|
||||||
|
|
||||||
__repr__ = simplerepr
|
__repr__ = simplerepr
|
||||||
|
|
||||||
|
def nested_options(self):
|
||||||
|
def get_class_by_object_literal_name(name):
|
||||||
|
for k, o in self.objects.iteritems():
|
||||||
|
if isinstance(o, Class) and o.object_literal.name == name:
|
||||||
|
return o
|
||||||
|
return None
|
||||||
|
|
||||||
|
for option in sorted(self.object_literal.prop_types.keys()):
|
||||||
|
types = self.object_literal.prop_types[option].split('|')
|
||||||
|
base, object_literal = None, None
|
||||||
|
for t in types:
|
||||||
|
if t in self.objects:
|
||||||
|
o = self.objects[t]
|
||||||
|
if isinstance(o, (Class, Symbol)):
|
||||||
|
if base:
|
||||||
|
raise RuntimeError('Multiple "class" types found for '
|
||||||
|
'option %s.%s: %s, %s.' %
|
||||||
|
(self.object_literal.name, option,
|
||||||
|
base.name, o.name))
|
||||||
|
base = o
|
||||||
|
elif isinstance(o, ObjectLiteral):
|
||||||
|
if object_literal:
|
||||||
|
raise RuntimeError('Multiple "literal" types found for '
|
||||||
|
'option %s.%s: %s, %s.' %
|
||||||
|
(self.object_literal.name, option,
|
||||||
|
object_literal.name, o.name))
|
||||||
|
object_literal = o
|
||||||
|
if object_literal:
|
||||||
|
if not base:
|
||||||
|
raise RuntimeError('%s "literal" type found for option %s.%s, '
|
||||||
|
'but no "class" type.' %
|
||||||
|
(object_literal.name, self.object_literal.name, option))
|
||||||
|
klass = get_class_by_object_literal_name(object_literal.name)
|
||||||
|
if not klass:
|
||||||
|
raise RuntimeError('No constructor taking a %s found.' %
|
||||||
|
object_literal.name)
|
||||||
|
yield option, object_literal, klass, base
|
||||||
|
|
||||||
def export(self):
|
def export(self):
|
||||||
lines = []
|
lines = []
|
||||||
if self.object_literal is None:
|
if self.object_literal is None:
|
||||||
@@ -51,10 +90,19 @@ class Class(Exportable):
|
|||||||
lines.append(' * @extends {%s}\n' % (self.name,))
|
lines.append(' * @extends {%s}\n' % (self.name,))
|
||||||
lines.append(' * @param {%s} options Options.\n' % (self.object_literal.extern_name(),))
|
lines.append(' * @param {%s} options Options.\n' % (self.object_literal.extern_name(),))
|
||||||
lines.append(' */\n')
|
lines.append(' */\n')
|
||||||
lines.append('%sExport = function(options) {\n' % (self.name,))
|
lines.append('%s = function(options) {\n' % (self.export_name(),))
|
||||||
lines.append(' /** @type {%s} */\n' % (self.object_literal.name,))
|
lines.append(' /** @type {%s} */\n' % (self.object_literal.name,))
|
||||||
lines.append(' var arg;\n');
|
lines.append(' var arg;\n');
|
||||||
lines.append(' if (goog.isDefAndNotNull(options)) {\n')
|
lines.append(' if (goog.isDefAndNotNull(options)) {\n')
|
||||||
|
# FIXME: we modify the user's options object
|
||||||
|
lines.append(''.join(
|
||||||
|
' if (!(options.%(o)s instanceof %(base)s)) {\n'
|
||||||
|
' options.%(o)s = new %(ctor)s(\n'
|
||||||
|
' /** @type {%(extern)s} */ (options.%(o)s));\n'
|
||||||
|
' }\n' %
|
||||||
|
{'o': o, 'base': b.name, 'ctor': k.export_name(),
|
||||||
|
'extern': ol.extern_name()} \
|
||||||
|
for o, ol, k, b in self.nested_options()))
|
||||||
lines.append(' arg = {')
|
lines.append(' arg = {')
|
||||||
lines.extend(','.join('\n %s: options.%s' % (key, key) for key in sorted(self.object_literal.prop_types.keys())))
|
lines.extend(','.join('\n %s: options.%s' % (key, key) for key in sorted(self.object_literal.prop_types.keys())))
|
||||||
lines.append('\n };\n')
|
lines.append('\n };\n')
|
||||||
@@ -66,10 +114,13 @@ class Class(Exportable):
|
|||||||
lines.append('goog.inherits(%sExport, %s);\n' % (self.name, self.name))
|
lines.append('goog.inherits(%sExport, %s);\n' % (self.name, self.name))
|
||||||
lines.append('goog.exportSymbol(\n')
|
lines.append('goog.exportSymbol(\n')
|
||||||
lines.append(' \'%s\',\n' % (self.name,))
|
lines.append(' \'%s\',\n' % (self.name,))
|
||||||
lines.append(' %sExport);\n' % (self.name,))
|
lines.append(' %s);\n' % (self.export_name(),))
|
||||||
lines.extend('goog.exportProperty(\n %s,\n \'%s\',\n %s.%s);\n' % (self.name, prop, self.name, prop) for prop in sorted(self.props))
|
lines.extend('goog.exportProperty(\n %s,\n \'%s\',\n %s.%s);\n' % (self.name, prop, self.name, prop) for prop in sorted(self.props))
|
||||||
return ''.join(lines)
|
return ''.join(lines)
|
||||||
|
|
||||||
|
def export_name(self):
|
||||||
|
return '%sExport' % self.name
|
||||||
|
|
||||||
|
|
||||||
class ObjectLiteral(Exportable):
|
class ObjectLiteral(Exportable):
|
||||||
|
|
||||||
@@ -101,7 +152,7 @@ class ObjectLiteral(Exportable):
|
|||||||
return '.'.join(self.extern_name().split('.')[:-1]) or None
|
return '.'.join(self.extern_name().split('.')[:-1]) or None
|
||||||
|
|
||||||
def provide(self):
|
def provide(self):
|
||||||
return 'goog.provide(\'%sType\');\n' % (self.name,)
|
return 'goog.provide(\'%s\');\n' % (self.name,)
|
||||||
|
|
||||||
def typedef(self):
|
def typedef(self):
|
||||||
lines = []
|
lines = []
|
||||||
@@ -161,7 +212,7 @@ def main(argv):
|
|||||||
object_literal = objects[object_literal_name]
|
object_literal = objects[object_literal_name]
|
||||||
if not isinstance(object_literal, ObjectLiteral):
|
if not isinstance(object_literal, ObjectLiteral):
|
||||||
raise RuntimeError(line) # Undefined object literal
|
raise RuntimeError(line) # Undefined object literal
|
||||||
klass = Class(name, object_literal)
|
klass = Class(name, object_literal, objects)
|
||||||
objects[name] = klass
|
objects[name] = klass
|
||||||
continue
|
continue
|
||||||
m = re.match(r'@exportObjectLiteral\s+(?P<name>\S+)\Z', line)
|
m = re.match(r'@exportObjectLiteral\s+(?P<name>\S+)\Z', line)
|
||||||
|
|||||||
Reference in New Issue
Block a user