From feefcee04a2f844534e13c4077c3ac2791961c66 Mon Sep 17 00:00:00 2001
From: Frederik Carlier <frederik.carlier@quamotion.mobi>
Date: Sun, 15 May 2016 22:21:32 +0200
Subject: [PATCH] Protocol Merging Improvements Support type references in
 arrays Support explicit type mappings

---
 .../ProtocolGenerator.Tests/CommandTests.cs   |  4 +-
 .../DeploymentItems.cs                        |  1 +
 ...omeDevTools.ProtocolGenerator.Tests.csproj |  3 ++
 .../ProtocolProcessorTests.cs                 | 51 ++++++++++++++++++-
 source/ProtocolGenerator/Program.cs           | 29 +++++++----
 source/ProtocolGenerator/ProtocolMerger.cs    |  6 +--
 source/ProtocolGenerator/ProtocolProcessor.cs | 33 ++++++++----
 source/ProtocolGenerator/Type.cs              |  5 ++
 8 files changed, 107 insertions(+), 25 deletions(-)

diff --git a/source/ProtocolGenerator.Tests/CommandTests.cs b/source/ProtocolGenerator.Tests/CommandTests.cs
index c3c2fd6..e4835cf 100644
--- a/source/ProtocolGenerator.Tests/CommandTests.cs
+++ b/source/ProtocolGenerator.Tests/CommandTests.cs
@@ -18,8 +18,8 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator.Tests
             var inspector11 = ProtocolProcessor.LoadProtocol(DeploymentItems.Inspector11, "inspector-1.1");
             var protocol = ProtocolProcessor.LoadProtocol(DeploymentItems.Protocol, "protocol");
 
-            ProtocolProcessor.ResolveTypeReferences(inspector11);
-            ProtocolProcessor.ResolveTypeReferences(protocol);
+            ProtocolProcessor.ResolveTypeReferences(inspector11, new Dictionary<string, string>());
+            ProtocolProcessor.ResolveTypeReferences(protocol, new Dictionary<string, string>());
 
             var stopScreencast10 = inspector11.GetDomain("Page").GetCommand("stopScreencast");
             var stopScreencastTip = protocol.GetDomain("Page").GetCommand("stopScreencast");
diff --git a/source/ProtocolGenerator.Tests/DeploymentItems.cs b/source/ProtocolGenerator.Tests/DeploymentItems.cs
index 7b97f4c..dec0e23 100644
--- a/source/ProtocolGenerator.Tests/DeploymentItems.cs
+++ b/source/ProtocolGenerator.Tests/DeploymentItems.cs
@@ -11,5 +11,6 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator.Tests
         public const string Inspector10 = "Inspector-1.0.json";
         public const string Inspector11 = "Inspector-1.1.json";
         public const string Protocol = "protocol.json";
+        public const string InspectoriOS8 = "Inspector-ios-8.0.json";
     }
 }
diff --git a/source/ProtocolGenerator.Tests/MasterDevs.ChromeDevTools.ProtocolGenerator.Tests.csproj b/source/ProtocolGenerator.Tests/MasterDevs.ChromeDevTools.ProtocolGenerator.Tests.csproj
index 338b3d7..8e37f65 100644
--- a/source/ProtocolGenerator.Tests/MasterDevs.ChromeDevTools.ProtocolGenerator.Tests.csproj
+++ b/source/ProtocolGenerator.Tests/MasterDevs.ChromeDevTools.ProtocolGenerator.Tests.csproj
@@ -67,6 +67,9 @@
       <Link>Inspector-1.0.json</Link>
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </None>
+    <None Include="..\ProtocolGenerator\Inspector-iOS-8.0.json">
+      <Link>Inspector-iOS-8.0.json</Link>
+    </None>
     <None Include="..\ProtocolGenerator\protocol.json">
       <Link>protocol.json</Link>
     </None>
diff --git a/source/ProtocolGenerator.Tests/ProtocolProcessorTests.cs b/source/ProtocolGenerator.Tests/ProtocolProcessorTests.cs
index 5745864..371d1ad 100644
--- a/source/ProtocolGenerator.Tests/ProtocolProcessorTests.cs
+++ b/source/ProtocolGenerator.Tests/ProtocolProcessorTests.cs
@@ -1,5 +1,7 @@
 using System;
+using System.Linq;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Collections.Generic;
 
 namespace MasterDevs.ChromeDevTools.ProtocolGenerator.Tests
 {
@@ -12,15 +14,60 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator.Tests
         /// </summary>
         [TestMethod]
         [DeploymentItem(DeploymentItems.Inspector10)]
-        public void ResolveTypeReferencesTest()
+        public void ResolveTypeReferencesCommandParameterTest()
         {
             Protocol p = ProtocolProcessor.LoadProtocol(DeploymentItems.Inspector10, "Chrome-1.0");
-            ProtocolProcessor.ResolveTypeReferences(p);
+            ProtocolProcessor.ResolveTypeReferences(p, new Dictionary<string, string>());
 
             var evaluateCommand = p.GetDomain("Runtime").GetCommand("evaluate");
             var frameIdParameter = evaluateCommand.GetParameter("frameId");
 
             Assert.AreEqual("string", frameIdParameter.TypeName);
         }
+
+        [TestMethod]
+        [DeploymentItem(DeploymentItems.Inspector10)]
+        public void ResolveTypeReferencesCommandParameterTest2()
+        {
+            Protocol p = ProtocolProcessor.LoadProtocol(DeploymentItems.Inspector10, "Chrome-1.0");
+            ProtocolProcessor.ResolveTypeReferences(p, new Dictionary<string, string>());
+
+            var addInspectedNodeCommand = p.GetDomain("Console").GetCommand("addInspectedNode");
+            var nodeId = addInspectedNodeCommand.GetParameter("nodeId");
+
+            Assert.AreEqual("integer", nodeId.TypeName);
+        }
+
+        [TestMethod]
+        [DeploymentItem(DeploymentItems.InspectoriOS8)]
+        public void ResolveTypeReferencesCommandReturnValueTest()
+        {
+            Dictionary<string, string> explicitMappings = new Dictionary<string, string>();
+            explicitMappings.Add("Page.Cookie", "Network.Cookie");
+
+            Protocol p = ProtocolProcessor.LoadProtocol(DeploymentItems.InspectoriOS8, "iOS-8.0");
+            ProtocolProcessor.ResolveTypeReferences(p, explicitMappings);
+
+            var getCookiesCommand = p.GetDomain("Page").GetCommand("getCookies");
+            var cookieArray = getCookiesCommand.Returns.Single();
+
+            Assert.AreEqual("Network.Cookie[]", cookieArray.TypeName);
+        }
+
+        [TestMethod]
+        [DeploymentItem(DeploymentItems.InspectoriOS8)]
+        public void ResolveTypeReferencesCommandReturnValueTest2()
+        {
+            Dictionary<string, string> explicitMappings = new Dictionary<string, string>();
+            explicitMappings.Add("GenericTypes.SearchMatch", "Debugger.SearchMatch");
+
+            Protocol p = ProtocolProcessor.LoadProtocol(DeploymentItems.InspectoriOS8, "iOS-8.0");
+            ProtocolProcessor.ResolveTypeReferences(p, explicitMappings);
+
+            var searchInResourceCommand = p.GetDomain("Page").GetCommand("searchInResource");
+            var searchMatchArray = searchInResourceCommand.Returns.Single();
+
+            Assert.AreEqual("Debugger.SearchMatch[]", searchMatchArray.TypeName);
+        }
     }
 }
diff --git a/source/ProtocolGenerator/Program.cs b/source/ProtocolGenerator/Program.cs
index 043194b..a375f34 100644
--- a/source/ProtocolGenerator/Program.cs
+++ b/source/ProtocolGenerator/Program.cs
@@ -27,22 +27,33 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator
 
         private static void Main(string[] args)
         {
+            // At this point in time, we only process the most recent Chrome
+            // and iOS (Safari) protocols.
             Dictionary<string, string> protocolFiles = new Dictionary<string, string>();
-            protocolFiles.Add("Chrome-0.1", "Inspector-0.1.json");
-            protocolFiles.Add("Chrome-1.0", "Inspector-1.0.json");
-            protocolFiles.Add("Chrome-1.1", "Inspector-1.1.json");
+            //protocolFiles.Add("Chrome-0.1", "Inspector-0.1.json");
+            //protocolFiles.Add("Chrome-1.0", "Inspector-1.0.json");
+            //protocolFiles.Add("Chrome-1.1", "Inspector-1.1.json");
             protocolFiles.Add("Chrome-Tip", "protocol.json");
-            protocolFiles.Add("iOS-7.0", "Inspector-iOS-7.0.json");
-            protocolFiles.Add("iOS-8.0", "Inspector-iOS-8.0.json");
-            protocolFiles.Add("iOS-9.0", "Inspector-iOS-9.0.json");
+            //protocolFiles.Add("iOS-7.0", "Inspector-iOS-7.0.json");
+            //protocolFiles.Add("iOS-8.0", "Inspector-iOS-8.0.json");
+            //protocolFiles.Add("iOS-9.0", "Inspector-iOS-9.0.json");
             protocolFiles.Add("iOS-9.3", "Inspector-iOS-9.3.json");
 
             Collection<Protocol> protocols = new Collection<Protocol>();
-            
-            foreach(var protocolFile in protocolFiles)
+
+            // "Explicit mappings" allow us to map one type reference to another. This is a
+            // rather hard-coded way of doing things, and is only used when the same type
+            // has different names accross different versions of the dev tools - e.g. the RGBA
+            // type which is named RGBAColor for Safari.
+            Dictionary<string, string> explicitMappings = new Dictionary<string, string>();
+            explicitMappings.Add("DOM.RGBAColor", "RGBA");
+            explicitMappings.Add("Page.Cookie", "Network.Cookie");
+            explicitMappings.Add("GenericTypes.SearchMatch", "Debugger.SearchMatch");
+
+            foreach (var protocolFile in protocolFiles)
             {
                 Protocol p = ProtocolProcessor.LoadProtocol(protocolFile.Value, protocolFile.Key);
-                ProtocolProcessor.ResolveTypeReferences(p);
+                ProtocolProcessor.ResolveTypeReferences(p, explicitMappings);
                 protocols.Add(p);
             }
 
diff --git a/source/ProtocolGenerator/ProtocolMerger.cs b/source/ProtocolGenerator/ProtocolMerger.cs
index e823b6b..cbdd168 100644
--- a/source/ProtocolGenerator/ProtocolMerger.cs
+++ b/source/ProtocolGenerator/ProtocolMerger.cs
@@ -18,12 +18,12 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator
                 }
                 else
                 {
-                    Merge(domain, target.Domains.Single(t => NameEqualityComparer.Instance.Equals(domain, t)));
+                    Merge(source, domain, target.Domains.Single(t => NameEqualityComparer.Instance.Equals(domain, t)));
                 }
             }
         }
 
-        static void Merge(Domain source, Domain target)
+        static void Merge(Protocol protocol, Domain source, Domain target)
         {
             foreach (var command in source.Commands)
             {
@@ -37,7 +37,7 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator
 
                     if(!targetCommand.Equals(command))
                     {
-                        Console.WriteLine($"{source.Name}:{command},{targetCommand}");
+                        Console.WriteLine($"{protocol.Alias};{source.Name};{command.Name};{command};{targetCommand}");
                     }
                     else
                     {
diff --git a/source/ProtocolGenerator/ProtocolProcessor.cs b/source/ProtocolGenerator/ProtocolProcessor.cs
index fa448dd..2286424 100644
--- a/source/ProtocolGenerator/ProtocolProcessor.cs
+++ b/source/ProtocolGenerator/ProtocolProcessor.cs
@@ -10,36 +10,36 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator
 {
     public class ProtocolProcessor
     {
-        public static void ResolveTypeReferences(Protocol protocol)
+        public static void ResolveTypeReferences(Protocol protocol, Dictionary<string, string> explicitMappings)
         {
             foreach (var domain in protocol.Domains)
             {
-                ResolveTypeReferences(protocol, domain);
+                ResolveTypeReferences(protocol, domain, explicitMappings);
             }
         }
 
-        public static void ResolveTypeReferences(Protocol protocol, Domain domain)
+        public static void ResolveTypeReferences(Protocol protocol, Domain domain, Dictionary<string, string> explicitMappings)
         {
             foreach (var command in domain.Commands)
             {
-                ResolveTypeReferences(protocol, domain, command);
+                ResolveTypeReferences(protocol, domain, command, explicitMappings);
             }
         }
 
-        public static void ResolveTypeReferences(Protocol protocol, Domain domain, Command command)
+        public static void ResolveTypeReferences(Protocol protocol, Domain domain, Command command, Dictionary<string, string> explicitMappings)
         {
             foreach (var parameter in command.Parameters)
             {
-                ResolveTypeReferences(protocol, domain, parameter);
+                ResolveTypeReferences(protocol, domain, parameter, explicitMappings);
             }
 
             foreach (var returnValue in command.Returns)
             {
-                ResolveTypeReferences(protocol, domain, returnValue);
+                ResolveTypeReferences(protocol, domain, returnValue, explicitMappings);
             }
         }
 
-        public static void ResolveTypeReferences(Protocol protocol, Domain domain, Property property)
+        public static void ResolveTypeReferences(Protocol protocol, Domain domain, Type property, Dictionary<string, string> explicitMappings)
         {
             if (property.TypeReference != null)
             {
@@ -64,12 +64,27 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator
                     throw new ArgumentOutOfRangeException();
                 }
 
+                string fullReferenceName = $"{referencedDomain.Name}.{referencedType.Name}";
+
                 // If it is a string, it can be resolved easily
-                if(referencedType.IsString())
+                if (referencedType.IsString())
                 {
                     property.Kind = "string";
                     property.TypeReference = null;
                 }
+                else if (referencedType.IsInteger())
+                {
+                    property.Kind = "integer";
+                    property.TypeReference = null;
+                }
+                else if (explicitMappings.ContainsKey(fullReferenceName))
+                {
+                    property.TypeReference = explicitMappings[fullReferenceName];
+                }
+            }
+            else if(property.Items != null)
+            {
+                ResolveTypeReferences(protocol, domain, property.Items, explicitMappings);
             }
         }
 
diff --git a/source/ProtocolGenerator/Type.cs b/source/ProtocolGenerator/Type.cs
index f383acf..7d8f8cf 100644
--- a/source/ProtocolGenerator/Type.cs
+++ b/source/ProtocolGenerator/Type.cs
@@ -144,6 +144,11 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator
             return string.Equals(this.Kind, "string", StringComparison.OrdinalIgnoreCase);
         }
 
+        public bool IsInteger()
+        {
+            return string.Equals(this.Kind, "integer", StringComparison.OrdinalIgnoreCase);
+        }
+
         public bool IsEnum()
         {
             return this.Enum.Any();
-- 
GitLab