Web Inspector: [Protocol] Genarate JS enum definitions.
authoreustas@chromium.org <eustas@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Feb 2013 07:50:22 +0000 (07:50 +0000)
committereustas@chromium.org <eustas@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Feb 2013 07:50:22 +0000 (07:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=110461

Reviewed by Pavel Feldman.

Generating corresponding type annotations
would help to compiler to point errors.

* inspector/CodeGeneratorInspector.py: Generate "registerEnum" records.
* inspector/InjectedScriptSource.js: Shadow compiler warning.
* inspector/front-end/InspectorBackend.js:
Added "registerEnum". Added "registerEnum" generation.
* inspector/front-end/NetworkManager.js: Use enum instead of literal.
* inspector/generate_protocol_externs.py: Generate enum typedefs.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@144265 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/inspector/CodeGeneratorInspector.py
Source/WebCore/inspector/InjectedScriptSource.js
Source/WebCore/inspector/front-end/InspectorBackend.js
Source/WebCore/inspector/front-end/NetworkManager.js
Source/WebCore/inspector/front-end/utilities.js
Source/WebCore/inspector/generate_protocol_externs.py

index 9a3c2d1..cb1f3e0 100644 (file)
@@ -1,3 +1,20 @@
+2013-02-27  Eugene Klyuchnikov  <eustas@chromium.org>
+
+        Web Inspector: [Protocol] Genarate JS enum definitions.
+        https://bugs.webkit.org/show_bug.cgi?id=110461
+
+        Reviewed by Pavel Feldman.
+
+        Generating corresponding type annotations
+        would help to compiler to point errors.
+
+        * inspector/CodeGeneratorInspector.py: Generate "registerEnum" records.
+        * inspector/InjectedScriptSource.js: Shadow compiler warning.
+        * inspector/front-end/InspectorBackend.js:
+        Added "registerEnum". Added "registerEnum" generation.
+        * inspector/front-end/NetworkManager.js: Use enum instead of literal.
+        * inspector/generate_protocol_externs.py: Generate enum typedefs.
+
 2013-02-27  Kunihiko Sakamoto  <ksakamoto@chromium.org>
 
         INPUT_MULTIPLE_FIELDS_UI: Step-up/-down of hour field should respect min/max attributes
index a40a575..049e099 100755 (executable)
@@ -32,6 +32,7 @@ import os.path
 import sys
 import string
 import optparse
+import re
 try:
     import json
 except ImportError:
@@ -99,6 +100,16 @@ def dash_to_camelcase(word):
     return ''.join(x.capitalize() or '-' for x in word.split('-'))
 
 
+def fix_camel_case(name):
+    refined = re.sub(r'-(\w)', lambda pat: pat.group(1).upper(), name)
+    refined = to_title_case(refined)
+    return re.sub(r'(?i)HTML|XML|WML|API', lambda pat: pat.group(0).upper(), refined)
+
+
+def to_title_case(name):
+    return name[:1].upper() + name[1:]
+
+
 class Capitalizer:
     @staticmethod
     def lower_camel_case_to_upper(str):
@@ -1861,6 +1872,18 @@ class Generator:
             if not domain_fixes.skip_js_bind:
                 Generator.backend_js_domain_initializer_list.append("InspectorBackend.register%sDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, \"%s\");\n" % (domain_name, domain_name))
 
+            if "types" in json_domain:
+                for json_type in json_domain["types"]:
+                    if "type" in json_type and json_type["type"] == "string" and "enum" in json_type:
+                        enum_name = "%s.%s" % (domain_name, json_type["id"])
+                        Generator.process_enum(json_type, enum_name)
+                    elif json_type["type"] == "object":
+                        if "properties" in json_type:
+                            for json_property in json_type["properties"]:
+                                if "type" in json_property and json_property["type"] == "string" and "enum" in json_property:
+                                    enum_name = "%s.%s%s" % (domain_name, json_type["id"], to_title_case(json_property["name"]))
+                                    Generator.process_enum(json_property, enum_name)
+
             if "events" in json_domain:
                 for json_event in json_domain["events"]:
                     Generator.process_event(json_event, domain_name, frontend_method_declaration_lines)
@@ -1895,6 +1918,15 @@ class Generator:
             Generator.backend_js_domain_initializer_list.append("\n")
 
     @staticmethod
+    def process_enum(json_enum, enum_name):
+        enum_members = []
+        for member in json_enum["enum"]:
+            enum_members.append("%s: \"%s\"" % (fix_camel_case(member), member))
+
+        Generator.backend_js_domain_initializer_list.append("InspectorBackend.registerEnum(\"%s\", {%s});\n" % (
+            enum_name, ", ".join(enum_members)))
+
+    @staticmethod
     def process_event(json_event, domain_name, frontend_method_declaration_lines):
         event_name = json_event["name"]
 
index 7000967..a38f776 100644 (file)
@@ -1089,7 +1089,7 @@ InjectedScript.CallFrameProxy._createScopeJson = function(scopeTypeCode, scopeOb
 
     return {
         object: injectedScript._wrapObject(scopeObject, groupId),
-        type: scopeTypeNames[scopeTypeCode]
+        type: /** @type {DebuggerAgent.ScopeType} */ (scopeTypeNames[scopeTypeCode])
     };
 }
 
index c2722b3..86d6c15 100644 (file)
@@ -60,20 +60,36 @@ InspectorBackendClass.prototype = {
         return callbackId;
     },
 
-    registerCommand: function(method, signature, replyArgs)
+    _getAgent: function(domain)
     {
-        var domainAndMethod = method.split(".");
-        var agentName = domainAndMethod[0] + "Agent";
+        var agentName = domain + "Agent";
         if (!window[agentName])
             window[agentName] = {};
+        return window[agentName];
+    },
 
-        window[agentName][domainAndMethod[1]] = this._sendMessageToBackend.bind(this, method, signature);
-        window[agentName][domainAndMethod[1]]["invoke"] = this._invoke.bind(this, method, signature);
+    registerCommand: function(method, signature, replyArgs)
+    {
+        var domainAndMethod = method.split(".");
+        var agent = this._getAgent(domainAndMethod[0]);
+
+        agent[domainAndMethod[1]] = this._sendMessageToBackend.bind(this, method, signature);
+        agent[domainAndMethod[1]]["invoke"] = this._invoke.bind(this, method, signature);
         this._replyArgs[method] = replyArgs;
 
         this._initialized = true;
     },
 
+    registerEnum: function(type, values)
+    {
+        var domainAndMethod = type.split(".");
+        var agent = this._getAgent(domainAndMethod[0]);
+
+        agent[domainAndMethod[1]] = values;
+
+        this._initialized = true;
+    },
+
     registerEvent: function(eventName, params)
     {
         this._eventArgs[eventName] = params;
@@ -277,11 +293,42 @@ InspectorBackendClass.prototype = {
                 rawTypes[domain.domain + "." + type.id] = jsTypes[type.type] || type.type;
             }
         }
+
+        function toUpperCase(groupIndex, group0, group1)
+        {
+            return [group0, group1][groupIndex].toUpperCase();
+        }
+        function generateEnum(enumName, items)
+        {
+            var members = []
+            for (var m = 0; m < items.length; ++m) {
+                var value = items[m];
+                var name = value.replace(/-(\w)/g, toUpperCase.bind(null, 1)).toTitleCase();
+                name = name.replace(/HTML|XML|WML|API/ig, toUpperCase.bind(null, 0));
+                members.push(name + ": \"" + value +"\"");
+            }
+            return "InspectorBackend.registerEnum(\"" + enumName + "s\", {" + members.join(", ") + "});\n";
+        }
     
         var result = [];
         for (var i = 0; i < domains.length; ++i) {
             var domain = domains[i];
 
+            var types = domain["types"] || [];
+            for (var j = 0; j < types.length; ++j) {
+                var type = types[j];
+                if ((type["type"] === "string") && type["enum"])
+                    result.push(generateEnum(domain.domain + "." + type.id, type["enum"]));
+                else if (type["type"] === "object") {
+                    var properties = type["properties"] || [];
+                    for (var k = 0; k < properties.length; ++k) {
+                        var property = properties[k];
+                        if ((property["type"] === "string") && property["enum"])
+                            result.push(generateEnum(domain.domain + "." + type.id + property["name"].toTitleCase(), property["enum"]));
+                    }
+                }
+            }
+
             var commands = domain["commands"] || [];    
             for (var j = 0; j < commands.length; ++j) {
                 var command = commands[j];
index 5f3576a..8eda186 100644 (file)
@@ -263,7 +263,7 @@ WebInspector.NetworkDispatcher.prototype = {
             // FIXME: move this check to the backend.
             if (!redirectResponse)
                 return;
-            this.responseReceived(requestId, frameId, loaderId, time, "Other", redirectResponse);
+            this.responseReceived(requestId, frameId, loaderId, time, PageAgent.ResourceType.Other, redirectResponse);
             networkRequest = this._appendRedirect(requestId, time, request.url);
         } else
             networkRequest = this._createNetworkRequest(requestId, frameId, loaderId, request.url, documentURL, initiator);
index e9ca47a..84c38f7 100644 (file)
@@ -138,6 +138,11 @@ String.prototype.trimURL = function(baseURLDomain)
     return result;
 }
 
+String.prototype.toTitleCase = function()
+{
+    return this.substring(0, 1).toUpperCase() + this.substring(1);
+}
+
 /**
  * @param {string} other
  * @return {number}
index 8600d16..beeaf54 100755 (executable)
@@ -27,6 +27,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+import re
+
 type_traits = {
     "any": "*",
     "string": "string",
@@ -46,6 +48,23 @@ def full_qualified_type_id(domain_name, type_id):
     return type_id
 
 
+def fix_camel_case(name):
+    refined = re.sub(r'-(\w)', lambda pat: pat.group(1).upper(), name)
+    refined = to_title_case(refined)
+    return re.sub(r'(?i)HTML|XML|WML|API', lambda pat: pat.group(0).upper(), refined)
+
+
+def to_title_case(name):
+    return name[:1].upper() + name[1:]
+
+
+def generate_enum(name, json):
+    enum_members = []
+    for member in json["enum"]:
+        enum_members.append("    %s: \"%s\"" % (fix_camel_case(member), member))
+    return "\n/** @enum {string} */\n%s = {\n%s\n};\n" % (name, (",\n".join(enum_members)))
+
+
 def param_type(domain_name, param):
     if "type" in param:
         if param["type"] == "array":
@@ -97,11 +116,18 @@ Protocol.Error;
                             suffix = ""
                             if ("optional" in property):
                                 suffix = "|undefined"
-                            typedef_args.append("%s:(%s%s)" % (property["name"], param_type(domain_name, property), suffix))
+                            if "enum" in property:
+                                enum_name = "%sAgent.%s%s" % (domain_name, type["id"], to_title_case(property["name"]))
+                                output_file.write(generate_enum(enum_name, property))
+                                typedef_args.append("%s:(%s%s)" % (property["name"], enum_name, suffix))
+                            else:
+                                typedef_args.append("%s:(%s%s)" % (property["name"], param_type(domain_name, property), suffix))
                     if (typedef_args):
                         output_file.write("\n/** @typedef {{%s}|null} */\n%sAgent.%s;\n" % (", ".join(typedef_args), domain_name, type["id"]))
                     else:
                         output_file.write("\n/** @typedef {Object} */\n%sAgent.%s;\n" % (domain_name, type["id"]))
+                elif type["type"] == "string" and "enum" in type:
+                    output_file.write(generate_enum("%sAgent.%s" % (domain_name, type["id"]), type))
                 elif type["type"] == "array":
                     suffix = ""
                     if ("optional" in property):