| Index: tools/json_schema_compiler/js_util.py
|
| diff --git a/tools/json_schema_compiler/js_externs_generator.py b/tools/json_schema_compiler/js_util.py
|
| similarity index 35%
|
| copy from tools/json_schema_compiler/js_externs_generator.py
|
| copy to tools/json_schema_compiler/js_util.py
|
| index 20796e9be56895efb7ed5591fac1abd179dee332..7e68e37e121944dc338d1028de92db698e34aff1 100644
|
| --- a/tools/json_schema_compiler/js_externs_generator.py
|
| +++ b/tools/json_schema_compiler/js_util.py
|
| @@ -1,154 +1,14 @@
|
| # Copyright 2015 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.
|
| -"""
|
| -Generator that produces an externs file for the Closure Compiler.
|
| -Note: This is a work in progress, and generated externs may require tweaking.
|
| -
|
| -See https://developers.google.com/closure/compiler/docs/api-tutorial3#externs
|
| -"""
|
|
|
| from code import Code
|
| -from model import *
|
| -from schema_util import *
|
| -
|
| -import os
|
| -import sys
|
| -from datetime import datetime
|
| -import re
|
| -
|
| -LICENSE = ("""// Copyright %s 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.
|
| -""" % datetime.now().year)
|
| -
|
| -INFO = """// This file was generated by:
|
| -// %s.
|
| -// NOTE: The format of types has changed. 'FooType' is now
|
| -// 'chrome.%s.FooType'.
|
| -// Please run the closure compiler before committing changes.
|
| -// See https://code.google.com/p/chromium/wiki/ClosureCompilation.
|
| -"""
|
| -
|
| -class JsExternsGenerator(object):
|
| - def Generate(self, namespace):
|
| - return _Generator(namespace).Generate()
|
| -
|
| -class _Generator(object):
|
| - def __init__(self, namespace):
|
| - self._namespace = namespace
|
| -
|
| - def Generate(self):
|
| - """Generates a Code object with the schema for the entire namespace.
|
| - """
|
| - c = Code()
|
| - (c.Append(LICENSE)
|
| - .Append()
|
| - .Append(INFO % (sys.argv[0], self._namespace.name))
|
| - .Append()
|
| - .Append('/** @fileoverview Externs generated from namespace: %s */' %
|
| - self._namespace.name)
|
| - .Append())
|
| -
|
| - c.Cblock(self._GenerateNamespaceObject())
|
| -
|
| - for js_type in self._namespace.types.values():
|
| - c.Cblock(self._GenerateType(js_type))
|
| -
|
| - for function in self._namespace.functions.values():
|
| - c.Cblock(self._GenerateFunction(function))
|
| -
|
| - for event in self._namespace.events.values():
|
| - c.Cblock(self._GenerateEvent(event))
|
| -
|
| - return c
|
| -
|
| - def _GenerateType(self, js_type):
|
| - """Given a Type object, returns the Code for this type's definition.
|
| - """
|
| - c = Code()
|
| - if js_type.property_type is PropertyType.ENUM:
|
| - c.Concat(self._GenerateEnumJsDoc(js_type))
|
| - else:
|
| - c.Concat(self._GenerateTypeJsDoc(js_type))
|
| -
|
| - return c
|
| -
|
| - def _GenerateEnumJsDoc(self, js_type):
|
| - """ Given an Enum Type object, returns the Code for the enum's definition.
|
| - """
|
| - c = Code()
|
| - (c.Sblock(line='/**', line_prefix=' * ')
|
| - .Append('@enum {string}')
|
| - .Append(self._GenerateSeeLink('type', js_type.simple_name))
|
| - .Eblock(' */'))
|
| - c.Append('chrome.%s.%s = {' % (self._namespace.name, js_type.name))
|
| -
|
| - def get_property_name(e):
|
| - # Enum properties are normified to be in ALL_CAPS_STYLE.
|
| - # Assume enum '1ring-rulesThemAll'.
|
| - # Transform to '1ring-rules_Them_All'.
|
| - e = re.sub(r'([a-z])([A-Z])', r'\1_\2', e)
|
| - # Transform to '1ring_rules_Them_All'.
|
| - e = re.sub(r'\W', '_', e)
|
| - # Transform to '_1ring_rules_Them_All'.
|
| - e = re.sub(r'^(\d)', r'_\1', e)
|
| - # Transform to '_1RING_RULES_THEM_ALL'.
|
| - return e.upper()
|
| -
|
| - c.Append('\n'.join(
|
| - [" %s: '%s'," % (get_property_name(v.name), v.name)
|
| - for v in js_type.enum_values]))
|
| - c.Append('};')
|
| - return c
|
| -
|
| - def _IsTypeConstructor(self, js_type):
|
| - """Returns true if the given type should be a @constructor. If this returns
|
| - false, the type is a typedef.
|
| - """
|
| - return any(prop.type_.property_type is PropertyType.FUNCTION
|
| - for prop in js_type.properties.values())
|
| -
|
| - def _GenerateTypeJsDoc(self, js_type):
|
| - """Generates the documentation for a type as a Code.
|
| -
|
| - Returns an empty code object if the object has no documentation.
|
| - """
|
| - c = Code()
|
| - c.Sblock(line='/**', line_prefix=' * ')
|
| -
|
| - if js_type.description:
|
| - for line in js_type.description.splitlines():
|
| - c.Append(line)
|
| -
|
| - is_constructor = self._IsTypeConstructor(js_type)
|
| - if is_constructor:
|
| - c.Comment('@constructor', comment_prefix = ' * ', wrap_indent=4)
|
| - else:
|
| - c.Concat(self._GenerateTypedef(js_type.properties))
|
| -
|
| - c.Append(self._GenerateSeeLink('type', js_type.simple_name))
|
| - c.Eblock(' */')
|
| -
|
| - var = 'chrome.%s.%s' % (js_type.namespace.name, js_type.simple_name)
|
| - if is_constructor: var += ' = function() {}'
|
| - var += ';'
|
| - c.Append(var)
|
| -
|
| - return c
|
| +from model import PropertyType
|
|
|
| - def _GenerateTypedef(self, properties):
|
| - """Given an OrderedDict of properties, returns a Code containing a @typedef.
|
| - """
|
| - if not properties: return Code()
|
| -
|
| - c = Code()
|
| - c.Append('@typedef {')
|
| - c.Concat(self._GenerateObjectDefinition(properties), new_line=False)
|
| - c.Append('}', new_line=False)
|
| - return c
|
| -
|
| - def _GenerateObjectDefinition(self, properties):
|
| +class JsUtil(object):
|
| + """A helper class for generating JS Code.
|
| + """
|
| + def GenerateObjectDefinition(self, namespace_name, properties):
|
| """Given an OrderedDict of properties, returns a Code containing the
|
| description of an object.
|
| """
|
| @@ -164,7 +24,7 @@ class _Generator(object):
|
| if not first:
|
| c.Append(',', new_line=False)
|
| first = False
|
| - js_type = self._TypeToJsType(prop.type_)
|
| + js_type = self._TypeToJsType(namespace_name, prop.type_)
|
| if prop.optional:
|
| js_type = (Code().
|
| Append('(').
|
| @@ -177,7 +37,7 @@ class _Generator(object):
|
|
|
| return c
|
|
|
| - def _GenerateFunctionJsDoc(self, function):
|
| + def GenerateFunctionJsDoc(self, namespace_name, function):
|
| """Generates the documentation for a function as a Code.
|
|
|
| Returns an empty code object if the object has no documentation.
|
| @@ -199,133 +59,82 @@ class _Generator(object):
|
| wrap_indent=4, new_line=False)
|
|
|
| for param in function.params:
|
| - append_field(c, 'param', self._TypeToJsType(param.type_), param.name,
|
| - param.optional, param.description)
|
| + append_field(c, 'param', self._TypeToJsType(namespace_name, param.type_),
|
| + param.name, param.optional, param.description)
|
|
|
| if function.callback:
|
| - append_field(c, 'param', self._FunctionToJsFunction(function.callback),
|
| + append_field(c, 'param',
|
| + self._FunctionToJsFunction(namespace_name,
|
| + function.callback),
|
| function.callback.name, function.callback.optional,
|
| function.callback.description)
|
|
|
| if function.returns:
|
| - append_field(c, 'return', self._TypeToJsType(function.returns),
|
| + append_field(c, 'return',
|
| + self._TypeToJsType(namespace_name, function.returns),
|
| '', False, function.returns.description)
|
|
|
| if function.deprecated:
|
| c.Append('@deprecated %s' % function.deprecated)
|
|
|
| - c.Append(self._GenerateSeeLink('method', function.name))
|
| + c.Append(self.GenerateSeeLink(namespace_name, 'method', function.name))
|
|
|
| c.Eblock(' */')
|
| return c
|
|
|
| - def _FunctionToJsFunction(self, function):
|
| + def _FunctionToJsFunction(self, namespace_name, function):
|
| """Converts a model.Function to a JS type (i.e., function([params])...)"""
|
| c = Code()
|
| c.Append('function(')
|
| for i, param in enumerate(function.params):
|
| - c.Concat(self._TypeToJsType(param.type_), new_line=False)
|
| + c.Concat(self._TypeToJsType(namespace_name, param.type_), new_line=False)
|
| if i is not len(function.params) - 1:
|
| c.Append(', ', new_line=False, strip_right=False)
|
| c.Append('):', new_line=False)
|
|
|
| if function.returns:
|
| - c.Concat(self._TypeToJsType(function.returns), new_line=False)
|
| + c.Concat(self._TypeToJsType(namespace_name, function.returns),
|
| + new_line=False)
|
| else:
|
| c.Append('void', new_line=False)
|
|
|
| return c
|
|
|
| - def _TypeToJsType(self, js_type):
|
| + def _TypeToJsType(self, namespace_name, js_type):
|
| """Converts a model.Type to a JS type (number, Array, etc.)"""
|
| if js_type.property_type in (PropertyType.INTEGER, PropertyType.DOUBLE):
|
| return Code().Append('number')
|
| if js_type.property_type is PropertyType.OBJECT:
|
| if js_type.properties:
|
| - return self._GenerateObjectDefinition(js_type.properties)
|
| + return self.GenerateObjectDefinition(namespace_name,
|
| + js_type.properties)
|
| return Code().Append('Object')
|
| if js_type.property_type is PropertyType.ARRAY:
|
| return (Code().Append('!Array<').
|
| - Concat(self._TypeToJsType(js_type.item_type), new_line=False).
|
| + Concat(self._TypeToJsType(namespace_name, js_type.item_type),
|
| + new_line=False).
|
| Append('>', new_line=False))
|
| if js_type.property_type is PropertyType.REF:
|
| - ref_type = '!chrome.%s.%s' % (self._namespace.name, js_type.ref_type)
|
| + ref_type = '!chrome.%s.%s' % (namespace_name, js_type.ref_type)
|
| return Code().Append(ref_type)
|
| if js_type.property_type is PropertyType.CHOICES:
|
| c = Code()
|
| c.Append('(')
|
| for i, choice in enumerate(js_type.choices):
|
| - c.Concat(self._TypeToJsType(choice), new_line=False)
|
| + c.Concat(self._TypeToJsType(namespace_name, choice), new_line=False)
|
| if i is not len(js_type.choices) - 1:
|
| c.Append('|', new_line=False)
|
| c.Append(')', new_line=False)
|
| return c
|
| if js_type.property_type is PropertyType.FUNCTION:
|
| - return self._FunctionToJsFunction(js_type.function)
|
| + return self._FunctionToJsFunction(namespace_name, js_type.function)
|
| if js_type.property_type is PropertyType.ANY:
|
| return Code().Append('*')
|
| if js_type.property_type.is_fundamental:
|
| return Code().Append(js_type.property_type.name)
|
| return Code().Append('?') # TODO(tbreisacher): Make this more specific.
|
|
|
| - def _GenerateFunction(self, function):
|
| - """Generates the code representing a function, including its documentation.
|
| - For example:
|
| -
|
| - /**
|
| - * @param {string} title The new title.
|
| - */
|
| - chrome.window.setTitle = function(title) {};
|
| - """
|
| - c = Code()
|
| - params = self._GenerateFunctionParams(function)
|
| - (c.Concat(self._GenerateFunctionJsDoc(function))
|
| - .Append('chrome.%s.%s = function(%s) {};' % (self._namespace.name,
|
| - function.name,
|
| - params))
|
| - )
|
| - return c
|
| -
|
| - def _GenerateEvent(self, event):
|
| - """Generates the code representing an event.
|
| - For example:
|
| -
|
| - /** @type {!ChromeEvent} */
|
| - chrome.bookmarks.onChildrenReordered;
|
| - """
|
| - c = Code()
|
| - c.Sblock(line='/**', line_prefix=' * ')
|
| - if (event.description):
|
| - c.Comment(event.description, comment_prefix='')
|
| - c.Append('@type {!ChromeEvent}')
|
| - c.Append(self._GenerateSeeLink('event', event.name))
|
| - c.Eblock(' */')
|
| - c.Append('chrome.%s.%s;' % (self._namespace.name, event.name))
|
| - return c
|
| -
|
| - def _GenerateNamespaceObject(self):
|
| - """Generates the code creating namespace object.
|
| - For example:
|
| -
|
| - /**
|
| - * @const
|
| - */
|
| - chrome.bookmarks = {};
|
| - """
|
| - c = Code()
|
| - (c.Append("""/**
|
| - * @const
|
| - */""")
|
| - .Append('chrome.%s = {};' % self._namespace.name))
|
| - return c
|
| -
|
| - def _GenerateFunctionParams(self, function):
|
| - params = function.params[:]
|
| - if function.callback:
|
| - params.append(function.callback)
|
| - return ', '.join(param.name for param in params)
|
| -
|
| - def _GenerateSeeLink(self, object_type, object_name):
|
| + def GenerateSeeLink(self, namespace_name, object_type, object_name):
|
| """Generates a @see link for a given API 'object' (type, method, or event).
|
| """
|
|
|
| @@ -335,4 +144,4 @@ class _Generator(object):
|
| # Luckily, the doc server has excellent url resolution, and knows exactly
|
| # what we mean. This saves us from needing any complicated logic here.
|
| return ('@see https://developer.chrome.com/extensions/%s#%s-%s' %
|
| - (self._namespace.name, object_type, object_name))
|
| + (namespace_name, object_type, object_name))
|
|
|