diff --git a/source/ProtocolGenerator/CollectionExtensions.cs b/source/ProtocolGenerator/CollectionExtensions.cs new file mode 100644 index 0000000000000000000000000000000000000000..d901618c06777480ee25a90aa6769dd0a0a2615d --- /dev/null +++ b/source/ProtocolGenerator/CollectionExtensions.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MasterDevs.ChromeDevTools.ProtocolGenerator +{ + static class CollectionExtensions + { + public static bool CollectionEqual<T>(this ICollection<T> x, ICollection<T> y) + { + if (x == null || y == null) + { + return false; + } + + if(x.Count != y.Count) + { + return false; + } + + return x.All(e => y.Contains(e)); + } + + public static int GetCollectionHashCode<T>(this ICollection<T> x) + { + int hash = 17; + + unchecked + { + foreach (var e in x) + { + hash = hash * 23 + e.GetHashCode(); + } + } + + return hash; + } + } +} diff --git a/source/ProtocolGenerator/Command.cs b/source/ProtocolGenerator/Command.cs index df3886ee795152cf0bfcc4c1d117f46b4f22b3ae..1707578d80217963d58d8b46ff13b1fd92c1fec0 100644 --- a/source/ProtocolGenerator/Command.cs +++ b/source/ProtocolGenerator/Command.cs @@ -1,4 +1,7 @@ -using System.Collections.ObjectModel; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Text; +using System.Linq; namespace MasterDevs.ChromeDevTools.ProtocolGenerator { @@ -46,5 +49,98 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator get; set; } + + public override bool Equals(object obj) + { + var other = obj as Command; + + if (other == null) + { + return false; + } + + bool equals = base.Equals(obj); + equals &= this.Returns.SequenceEqual(other.Returns); + equals &= Property.Equals(this.Error, other.Error); + equals &= this.Handlers.CollectionEqual(other.Handlers); + equals &= this.Parameters.SequenceEqual(other.Parameters); + return equals; + } + + public override int GetHashCode() + { + unchecked + { + int hash = base.GetHashCode(); + hash = hash * 23 + this.Redirect.GetHashCode(); + + if (this.Error != null) + { + hash = hash * 23 + this.Error.GetHashCode(); + } + + hash = hash * 23 + this.Handlers.GetCollectionHashCode(); + hash = hash * 23 + this.Parameters.GetCollectionHashCode(); + return hash; + } + } + + public override string ToString() + { + StringBuilder name = new StringBuilder(); + + if (this.Returns.Count > 0) + { + name.Append("("); + bool isFirst = true; + + foreach (var p in this.Returns) + { + if (isFirst) + { + isFirst = false; + } + else + { + name.Append(", "); + } + + name.Append(p.TypeName); + name.Append(" "); + name.Append(p.Name); + } + + name.Append(") "); + } + else + { + name.Append("void "); + } + + name.Append(this.Name); + + name.Append("("); + + bool isFirstParam = true; + foreach (var p in this.Parameters) + { + if (isFirstParam) + { + isFirstParam = false; + } + else + { + name.Append(", "); + } + + name.Append(p.TypeName); + name.Append(" "); + name.Append(p.Name); + } + + name.Append(")"); + + return name.ToString(); + } } } diff --git a/source/ProtocolGenerator/MasterDevs.ChromeDevTools.ProtocolGenerator.csproj b/source/ProtocolGenerator/MasterDevs.ChromeDevTools.ProtocolGenerator.csproj index 4a58f80391dbf58d9e10dd4e977a50dc697846f2..a7206bdc45c6164a151ef9951dd4acead84a621f 100644 --- a/source/ProtocolGenerator/MasterDevs.ChromeDevTools.ProtocolGenerator.csproj +++ b/source/ProtocolGenerator/MasterDevs.ChromeDevTools.ProtocolGenerator.csproj @@ -50,14 +50,17 @@ <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> + <Compile Include="CollectionExtensions.cs" /> <Compile Include="Command.cs" /> <Compile Include="Domain.cs" /> <Compile Include="Event.cs" /> + <Compile Include="NameEqualityComparer.cs" /> <Compile Include="Program.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Property.cs" /> <Compile Include="Protocol.cs" /> <Compile Include="ProtocolItem.cs" /> + <Compile Include="ProtocolMerger.cs" /> <Compile Include="Type.cs" /> <Compile Include="Version.cs" /> </ItemGroup> diff --git a/source/ProtocolGenerator/NameEqualityComparer.cs b/source/ProtocolGenerator/NameEqualityComparer.cs new file mode 100644 index 0000000000000000000000000000000000000000..75287f9b470f9188e6efe7a6baeb0d8e4caa38d6 --- /dev/null +++ b/source/ProtocolGenerator/NameEqualityComparer.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MasterDevs.ChromeDevTools.ProtocolGenerator +{ + class NameEqualityComparer : EqualityComparer<ProtocolItem> + { + public static NameEqualityComparer Instance + { get; } = new NameEqualityComparer(); + + public override bool Equals(ProtocolItem x, ProtocolItem y) + { + if (x == null || y == null) + { + return false; + } + + return string.Equals(x.Name, y.Name, StringComparison.OrdinalIgnoreCase); + } + + public override int GetHashCode(ProtocolItem obj) + { + if (obj == null) + { + throw new ArgumentNullException(nameof(obj)); + } + + return StringComparer.OrdinalIgnoreCase.GetHashCode(obj.Name); + } + } +} diff --git a/source/ProtocolGenerator/Program.cs b/source/ProtocolGenerator/Program.cs index 0b16d5fe7e0267808d66d16d60ea191d355ff2fb..4315bbb2f286f3313e16e0410e3b50eb6d095e1e 100644 --- a/source/ProtocolGenerator/Program.cs +++ b/source/ProtocolGenerator/Program.cs @@ -2,6 +2,7 @@ using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Text; @@ -23,20 +24,61 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator private static Dictionary<string, List<string>> _DomainEvents = new Dictionary<string, List<string>>(); private static Dictionary<string, string> _SimpleTypes = new Dictionary<string, string>(); - private static Protocol LoadProtocol(string path) + private static Protocol LoadProtocol(string path, string alias) { string json = File.ReadAllText(path); JsonSerializerSettings settings = new JsonSerializerSettings(); settings.MissingMemberHandling = MissingMemberHandling.Error; settings.MetadataPropertyHandling = MetadataPropertyHandling.Ignore; Protocol p = JsonConvert.DeserializeObject<Protocol>(json, settings); + p.SourceFile = path; + p.Alias = alias; + + foreach(var domain in p.Domains) + { + foreach(var command in domain.Commands) + { + command.SupportedBy.Add(alias); + } + + foreach(var @event in domain.Events) + { + @event.SupportedBy.Add(alias); + } + + foreach(var type in domain.Types) + { + type.SupportedBy.Add(alias); + } + } + return p; } private static void Main(string[] args) { - var filePath = "protocol.json"; - var protocolObject = LoadProtocol(filePath); + 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-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-9.3", "Inspector-iOS-9.3.json"); + + Collection<Protocol> protocols = new Collection<Protocol>(); + + foreach(var protocolFile in protocolFiles) + { + protocols.Add(LoadProtocol(protocolFile.Value, protocolFile.Key)); + } + + Protocol protocolObject = new Protocol(); + foreach(var protocol in protocols) + { + ProtocolMerger.Merge(protocol, protocolObject); + } var outputFolder = "OutputProtocol"; if (args.Length > 0) diff --git a/source/ProtocolGenerator/Protocol.cs b/source/ProtocolGenerator/Protocol.cs index ae206ed86f9019041adf5f86c381dc4faa1895e3..f4d70de17c9fe68d1346230c90eae1bc68290e16 100644 --- a/source/ProtocolGenerator/Protocol.cs +++ b/source/ProtocolGenerator/Protocol.cs @@ -4,6 +4,12 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator { class Protocol { + public Protocol() + { + this.Compatible = new Collection<string>(); + this.Domains = new Collection<Domain>(); + } + public Collection<string> Compatible { get; @@ -21,5 +27,17 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator get; set; } + + public string SourceFile + { + get; + set; + } + + public string Alias + { + get; + set; + } } } diff --git a/source/ProtocolGenerator/ProtocolItem.cs b/source/ProtocolGenerator/ProtocolItem.cs index 61bae95f698cfcfecdfb486507599265f205e729..984fcda35bccb19566c2a63c7bbaed12d27a5a31 100644 --- a/source/ProtocolGenerator/ProtocolItem.cs +++ b/source/ProtocolGenerator/ProtocolItem.cs @@ -1,7 +1,16 @@ -namespace MasterDevs.ChromeDevTools.ProtocolGenerator +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace MasterDevs.ChromeDevTools.ProtocolGenerator { abstract class ProtocolItem { + public ProtocolItem() + { + this.SupportedBy = new Collection<string>(); + } + public virtual string Description { get; @@ -20,9 +29,64 @@ set; } + public Collection<string> SupportedBy + { + get; + } + public override string ToString() { return this.Name; } + + public static bool Equals(ProtocolItem a, ProtocolItem b) + { + if (a == null && b == null) + { + return true; + } + + if (a == null || b == null) + { + return false; + } + + if (a.GetType() != b.GetType()) + { + return false; + } + + return a.Equals(b); + } + + public override bool Equals(object obj) + { + // In the Equals method, we only include properties which would impact how + // messages are serialized over the wire. E.g.: because the description does not + // impact this, but the name does, the description is ignored but the name is included. + var other = obj as ProtocolItem; + + if (other == null) + { + return false; + } + + return string.Equals(other.Name, this.Name, StringComparison.OrdinalIgnoreCase); + } + + public override int GetHashCode() + { + unchecked + { + int hash = 17; + + if (this.Name != null) + { + hash = hash * 23 + StringComparer.OrdinalIgnoreCase.GetHashCode(this.Name); + } + + return hash; + } + } } } diff --git a/source/ProtocolGenerator/ProtocolMerger.cs b/source/ProtocolGenerator/ProtocolMerger.cs new file mode 100644 index 0000000000000000000000000000000000000000..e823b6b552ef2ac1f2c11e654d99dc2e6c06d8d2 --- /dev/null +++ b/source/ProtocolGenerator/ProtocolMerger.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MasterDevs.ChromeDevTools.ProtocolGenerator +{ + class ProtocolMerger + { + public static void Merge(Protocol source, Protocol target) + { + foreach (var domain in source.Domains) + { + if (!target.Domains.Contains(domain, NameEqualityComparer.Instance)) + { + target.Domains.Add(domain); + } + else + { + Merge(domain, target.Domains.Single(t => NameEqualityComparer.Instance.Equals(domain, t))); + } + } + } + + static void Merge(Domain source, Domain target) + { + foreach (var command in source.Commands) + { + if (!target.Commands.Contains(command, NameEqualityComparer.Instance)) + { + target.Commands.Add(command); + } + else + { + var targetCommand = target.Commands.Single(t => NameEqualityComparer.Instance.Equals(command, t)); + + if(!targetCommand.Equals(command)) + { + Console.WriteLine($"{source.Name}:{command},{targetCommand}"); + } + else + { + foreach (var v in command.SupportedBy) + { + targetCommand.SupportedBy.Add(v); + } + } + } + } + + foreach (var @event in source.Events) + { + if (!target.Events.Contains(@event, NameEqualityComparer.Instance)) + { + target.Events.Add(@event); + } + else + { + } + } + + foreach (var type in source.Types) + { + if (!target.Types.Contains(type, NameEqualityComparer.Instance)) + { + target.Types.Add(type); + } + else + { + } + } + } + } +} diff --git a/source/ProtocolGenerator/Type.cs b/source/ProtocolGenerator/Type.cs index 79c70838ea69b7751fb0a745b6d40946404159a4..b10c7b9ba1bfd44b41a9151dead9e991a503f2eb 100644 --- a/source/ProtocolGenerator/Type.cs +++ b/source/ProtocolGenerator/Type.cs @@ -1,4 +1,6 @@ using Newtonsoft.Json; +using System; +using System.Collections.Generic; using System.Collections.ObjectModel; namespace MasterDevs.ChromeDevTools.ProtocolGenerator @@ -7,8 +9,8 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator { public Type() { - this.Enum = new Collection<string>(); - this.Properties = new Collection<Property>(); + this.Enum = new HashSet<string>(); + this.Properties = new HashSet<Property>(); } [JsonProperty(PropertyName = "Id")] @@ -18,20 +20,20 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator set; } - [JsonProperty(PropertyName ="type")] + [JsonProperty(PropertyName = "type")] public string Kind { get; set; } - public Collection<string> Enum + public HashSet<string> Enum { get; set; } - public Collection<Property> Properties + public HashSet<Property> Properties { get; set; @@ -61,5 +63,77 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator get; set; } + + public string TypeName + { + get + { + if (this.TypeReference != null) + { + return this.TypeReference; + } + else if (this.Items != null) + { + return this.Items.Name + "[]"; + } + else if(this.Kind != null && this.Kind != "object") + { + return this.Kind; + } + else + { + return this.Name; + } + } + } + public override bool Equals(object obj) + { + var other = obj as Type; + + if (other == null) + { + return false; + } + + return base.Equals(obj) + && string.Equals(this.Kind, other.Kind, StringComparison.OrdinalIgnoreCase) + && this.Enum.SetEquals(other.Enum) + && this.Properties.SetEquals(other.Properties) + && Type.Equals(this.Items, other.Items) + && this.MinItems == other.MinItems + && this.MaxItems == other.MaxItems + && string.Equals(this.TypeReference, other.TypeReference, StringComparison.OrdinalIgnoreCase); + } + + public override int GetHashCode() + { + unchecked + { + int hash = base.GetHashCode(); + + if (this.Kind != null) + { + hash = hash * 23 + StringComparer.OrdinalIgnoreCase.GetHashCode(this.Kind); + } + + hash = hash * 23 + this.Enum.GetCollectionHashCode(); + hash = hash * 23 + this.Properties.GetCollectionHashCode(); + + if (this.Items != null) + { + hash = hash * 23 + this.Items.GetHashCode(); + } + + hash = hash * 23 + this.MinItems.GetHashCode(); + hash = hash * 23 + this.MaxItems.GetHashCode(); + + if (this.TypeReference != null) + { + hash = hash * 23 + StringComparer.OrdinalIgnoreCase.GetHashCode(this.TypeReference); + } + + return hash; + } + } } }