Commit d68755a4 authored by rdevlin.cronin's avatar rdevlin.cronin Committed by Commit bot

[Extension API Extern Generation] Auto-generate enums

Enums used to simply be strings, but now we expose them (as string constants)
on the api object as part of the extension bindings. As such, it's appropriate
to have the externs generate an enum definition for them.

BUG=469920

Review URL: https://codereview.chromium.org/1015033003

Cr-Commit-Position: refs/heads/master@{#322086}
parent 105d38dd
......@@ -471,6 +471,16 @@ def Load(filename):
contents = f.read()
f.close()
return Process(contents, filename)
def Process(contents, filename):
'''
Processes the contents of a file and returns an equivalent Python dictionary
in a format that the JSON schema compiler expects to see. (Separate from
Load primarily for testing purposes.)
'''
idl = idl_parser.IDLParser().ParseData(contents, filename)
idl_schema = IDLSchema(idl)
return idl_schema.process()
......
......@@ -38,11 +38,11 @@ class _Generator(object):
self._namespace.name)
.Append())
c.Cblock(self._GenerateNamespaceObject())
for js_type in self._namespace.types.values():
c.Cblock(self._GenerateType(js_type))
c.Cblock(self._GenerateNamespaceObject())
for function in self._namespace.functions.values():
c.Cblock(self._GenerateFunction(function))
......@@ -53,22 +53,24 @@ class _Generator(object):
def _GenerateType(self, js_type):
"""Given a Type object, returns the Code for this type's definition.
"""
c = Code()
# Since enums are just treated as strings for now, don't generate their
# type.
if js_type.property_type is PropertyType.ENUM:
return c
c.Concat(self._GenerateTypeJsDoc(js_type))
c.Concat(self._GenerateEnumJsDoc(js_type))
else:
c.Concat(self._GenerateTypeJsDoc(js_type))
var = 'var ' + js_type.simple_name
if self._IsTypeConstructor(js_type): var += ' = function()'
var += ';'
c.Append(var)
return c
def _GenerateEnumJsDoc(self, js_type):
""" Given an Enum Type object, returns the Code for the enum's definition.
"""
c = Code()
c.Append('/**').Append(' * @enum {string}').Append(' */')
c.Append('chrome.%s.%s = {' % (self._namespace.name, js_type.name))
c.Append('\n'.join(
[" %s: '%s'," % (v.name, v.name) for v in js_type.enum_values]))
c.Append('};')
return c
def _IsTypeConstructor(self, js_type):
......@@ -90,12 +92,19 @@ class _Generator(object):
for line in js_type.description.splitlines():
c.Comment(line, comment_prefix = ' * ')
if self._IsTypeConstructor(js_type):
is_constructor = self._IsTypeConstructor(js_type)
if is_constructor:
c.Comment('@constructor', comment_prefix = ' * ')
else:
c.Concat(self._GenerateTypedef(js_type.properties))
c.Append(' */')
var = 'var ' + js_type.simple_name
if is_constructor: var += ' = function() {}'
var += ';'
c.Append(var)
return c
def _GenerateTypedef(self, properties):
......@@ -173,7 +182,12 @@ class _Generator(object):
elif js_type.property_type is PropertyType.ARRAY:
return 'Array'
elif js_type.property_type is PropertyType.REF:
return js_type.ref_type
ref_type = js_type.ref_type
# Enums are defined as chrome.fooAPI.MyEnum, but types are defined simply
# as MyType.
if self._namespace.types[ref_type].property_type is PropertyType.ENUM:
ref_type = 'chrome.%s.%s' % (self._namespace.name, ref_type)
return ref_type
elif js_type.property_type.is_fundamental:
return js_type.property_type.name
else:
......
#!/usr/bin/env python
# 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.
import idl_schema
from js_externs_generator import JsExternsGenerator
from datetime import datetime
import model
import unittest
# The contents of a fake idl file.
fake_idl = """
// 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.
// A totally fake API.
namespace fakeApi {
enum Greek {
ALPHA,
BETA,
GAMMA,
DELTA
};
dictionary Bar {
long num;
};
dictionary Baz {
DOMString str;
long num;
boolean b;
Greek letter;
long[] arr;
Bar obj;
long? maybe;
};
callback VoidCallback = void();
interface Functions {
// Does something exciting!
// |baz| : The baz to use.
static void doSomething(Baz baz, optional VoidCallback callback);
};
};
"""
# The output we expect from our fake idl file.
expected_output = """// 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.
/** @fileoverview Externs generated from namespace: fakeApi */
/**
* @const
*/
chrome.fakeApi = {};
/**
* @enum {string}
*/
chrome.fakeApi.Greek = {
ALPHA: 'ALPHA',
BETA: 'BETA',
GAMMA: 'GAMMA',
DELTA: 'DELTA',
};
/**
* @typedef {{
* num: number
* }}
*/
var Bar;
/**
* @typedef {{
* str: string,
* num: number,
* b: boolean,
* letter: chrome.fakeApi.Greek,
* arr: Array,
* obj: Bar,
* maybe: (number|undefined)
* }}
*/
var Baz;
/**
* Does something exciting!
* @param {Baz} baz The baz to use.
* @param {Function=} callback
*/
chrome.fakeApi.doSomething = function(baz, callback) {};
""" % datetime.now().year
class JsExternGeneratorTest(unittest.TestCase):
def testBasic(self):
filename = 'fake_api.idl'
api_def = idl_schema.Process(fake_idl, filename)
m = model.Model()
namespace = m.AddNamespace(api_def[0], filename)
self.assertEquals(expected_output,
JsExternsGenerator().Generate(namespace).Render())
if __name__ == '__main__':
unittest.main()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment