diff --git a/source/ChromeDevTools/MasterDevs.ChromeDevTools.csproj b/source/ChromeDevTools/MasterDevs.ChromeDevTools.csproj index 5c08970b191b5e4cd62f325fcaa6eb4934e51827..c8c40e0002b9fbb8417172315a19559d640a0dcc 100644 --- a/source/ChromeDevTools/MasterDevs.ChromeDevTools.csproj +++ b/source/ChromeDevTools/MasterDevs.ChromeDevTools.csproj @@ -880,6 +880,7 @@ <Compile Include="Protocol\Worker\WorkerCreatedEvent.cs" /> <Compile Include="Protocol\Worker\WorkerTerminatedEvent.cs" /> <Compile Include="Serialization\MessageContractResolver.cs" /> + <Compile Include="SupportedByAttribute.cs" /> </ItemGroup> <ItemGroup> <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> diff --git a/source/ChromeDevTools/SupportedByAttribute.cs b/source/ChromeDevTools/SupportedByAttribute.cs new file mode 100644 index 0000000000000000000000000000000000000000..73fb8cf2744063a1d1a39c0a33821cbfd0826d7a --- /dev/null +++ b/source/ChromeDevTools/SupportedByAttribute.cs @@ -0,0 +1,24 @@ +using System; + +namespace MasterDevs.ChromeDevTools +{ + [AttributeUsage(AttributeTargets.Class)] + public class SupportedByAttribute : Attribute + { + public SupportedByAttribute(string browser) + { + if (browser == null) + { + throw new ArgumentNullException(nameof(browser)); + } + + this.Browser = browser; + } + + public string Browser + { + get; + set; + } + } +} diff --git a/source/MasterDevs.ChromeDevTools.sln b/source/MasterDevs.ChromeDevTools.sln index 521d04e064ce6c4905d1f4df693e98e8a9179778..a20ee809d611088a42c468cbc9271e130d10190d 100644 --- a/source/MasterDevs.ChromeDevTools.sln +++ b/source/MasterDevs.ChromeDevTools.sln @@ -1,7 +1,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +VisualStudioVersion = 14.0.25123.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{0D43D20B-6D51-4CBC-BD30-F17B8CA65678}" ProjectSection(SolutionItems) = preProject @@ -22,6 +22,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MasterDevs.ChromeDevTools.P EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MasterDevs.ChromeDevTools.Sample", "Sample\MasterDevs.ChromeDevTools.Sample.csproj", "{36138327-0A72-44E3-B9DB-C4E6155AAFD5}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MasterDevs.ChromeDevTools.ProtocolGenerator.Tests", "ProtocolGenerator.Tests\MasterDevs.ChromeDevTools.ProtocolGenerator.Tests.csproj", "{4C3A1910-79C5-43C0-8599-89921482B38B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -40,6 +42,10 @@ Global {36138327-0A72-44E3-B9DB-C4E6155AAFD5}.Debug|Any CPU.Build.0 = Debug|Any CPU {36138327-0A72-44E3-B9DB-C4E6155AAFD5}.Release|Any CPU.ActiveCfg = Release|Any CPU {36138327-0A72-44E3-B9DB-C4E6155AAFD5}.Release|Any CPU.Build.0 = Release|Any CPU + {4C3A1910-79C5-43C0-8599-89921482B38B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4C3A1910-79C5-43C0-8599-89921482B38B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4C3A1910-79C5-43C0-8599-89921482B38B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4C3A1910-79C5-43C0-8599-89921482B38B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/source/ProtocolGenerator.Tests/CommandTests.cs b/source/ProtocolGenerator.Tests/CommandTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..e4835cf75db2f9c041a724f7cb26822ee5c8a95f --- /dev/null +++ b/source/ProtocolGenerator.Tests/CommandTests.cs @@ -0,0 +1,35 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MasterDevs.ChromeDevTools.ProtocolGenerator.Tests +{ + [TestClass] + public class CommandTests + { + [TestMethod] + [DeploymentItem(DeploymentItems.Inspector11)] + [DeploymentItem(DeploymentItems.Protocol)] + public void EqualsTest() + { + var inspector11 = ProtocolProcessor.LoadProtocol(DeploymentItems.Inspector11, "inspector-1.1"); + var protocol = ProtocolProcessor.LoadProtocol(DeploymentItems.Protocol, "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"); + + // Quick fact check: both methods have the same string equivalent, + // void stopScreencast() + Assert.AreEqual<string>(stopScreencast10.ToString(), stopScreencastTip.ToString()); + + Assert.IsTrue(stopScreencast10.Equals(stopScreencastTip)); + Assert.IsTrue(stopScreencastTip.Equals(stopScreencast10)); + } + } +} diff --git a/source/ProtocolGenerator.Tests/DeploymentItems.cs b/source/ProtocolGenerator.Tests/DeploymentItems.cs new file mode 100644 index 0000000000000000000000000000000000000000..dec0e235aab89c6757e46a6f6e525dfaf32766c2 --- /dev/null +++ b/source/ProtocolGenerator.Tests/DeploymentItems.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MasterDevs.ChromeDevTools.ProtocolGenerator.Tests +{ + class DeploymentItems + { + 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 new file mode 100644 index 0000000000000000000000000000000000000000..8e37f6572a6f57b277fbd82e2e651b5ae863513c --- /dev/null +++ b/source/ProtocolGenerator.Tests/MasterDevs.ChromeDevTools.ProtocolGenerator.Tests.csproj @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{4C3A1910-79C5-43C0-8599-89921482B38B}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>MasterDevs.ChromeDevTools.ProtocolGenerator.Tests</RootNamespace> + <AssemblyName>MasterDevs.ChromeDevTools.ProtocolGenerator.Tests</AssemblyName> + <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion> + <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> + <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath> + <IsCodedUITest>False</IsCodedUITest> + <TestProjectType>UnitTest</TestProjectType> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + </ItemGroup> + <Choose> + <When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'"> + <ItemGroup> + <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" /> + </ItemGroup> + </When> + <Otherwise> + <ItemGroup> + <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" /> + </ItemGroup> + </Otherwise> + </Choose> + <ItemGroup> + <Compile Include="CommandTests.cs" /> + <Compile Include="DeploymentItems.cs" /> + <Compile Include="ProtocolProcessorTests.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="TypeTests.cs" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\ProtocolGenerator\MasterDevs.ChromeDevTools.ProtocolGenerator.csproj"> + <Project>{97c7fcf5-1964-4878-b7cd-63448ca403b1}</Project> + <Name>MasterDevs.ChromeDevTools.ProtocolGenerator</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <None Include="..\ProtocolGenerator\Inspector-1.0.json"> + <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> + </ItemGroup> + <Choose> + <When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'"> + <ItemGroup> + <Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + </ItemGroup> + </When> + </Choose> + <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" /> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project> \ No newline at end of file diff --git a/source/ProtocolGenerator.Tests/Properties/AssemblyInfo.cs b/source/ProtocolGenerator.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000000000000000000000000000000000..27cd8c0576a8621539ffbd4dc216261072a9a4e3 --- /dev/null +++ b/source/ProtocolGenerator.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MasterDevs.ChromeDevTools.ProtocolGenerator.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MasterDevs.ChromeDevTools.ProtocolGenerator.Tests")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("4c3a1910-79c5-43c0-8599-89921482b38b")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/source/ProtocolGenerator.Tests/ProtocolProcessorTests.cs b/source/ProtocolGenerator.Tests/ProtocolProcessorTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..371d1adbd30d98380de0a837e17c090d22a54c72 --- /dev/null +++ b/source/ProtocolGenerator.Tests/ProtocolProcessorTests.cs @@ -0,0 +1,73 @@ +using System; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Collections.Generic; + +namespace MasterDevs.ChromeDevTools.ProtocolGenerator.Tests +{ + [TestClass] + public class ProtocolProcessorTests + { + /// <summary> + /// Loads the Chrome-1.0 protocol and makes sure the type <c>Network.FrameId</c> type reference in the + /// <c>Runtime.Evaluate</c> command is resolved correctly to the <c>string</c> primitive. + /// </summary> + [TestMethod] + [DeploymentItem(DeploymentItems.Inspector10)] + public void ResolveTypeReferencesCommandParameterTest() + { + Protocol p = ProtocolProcessor.LoadProtocol(DeploymentItems.Inspector10, "Chrome-1.0"); + 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.Tests/TypeTests.cs b/source/ProtocolGenerator.Tests/TypeTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..1b0f6d76e2580c2da2cc4f18d6049dfd255ab42b --- /dev/null +++ b/source/ProtocolGenerator.Tests/TypeTests.cs @@ -0,0 +1,39 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MasterDevs.ChromeDevTools.ProtocolGenerator.Tests +{ + [TestClass] + public class TypeTests + { + + [TestMethod] + [DeploymentItem(DeploymentItems.Inspector10)] + public void TypeNameTest() + { + Protocol p = ProtocolProcessor.LoadProtocol(DeploymentItems.Inspector10, "Chrome-1.0"); + + var evaluateCommand = p.GetDomain("Page").GetCommand("searchInResource"); + var result = evaluateCommand.Returns.Single(); + + Assert.AreEqual("SearchMatch[]", result.TypeName.ToString()); + } + + [TestMethod] + [DeploymentItem(DeploymentItems.Inspector10)] + public void ToStringTest() + { + Protocol p = ProtocolProcessor.LoadProtocol(DeploymentItems.Inspector10, "Chrome-1.0"); + + var evaluateCommand = p.GetDomain("Page").GetCommand("searchInResource"); + var result = evaluateCommand.Returns.Single(); + var items = result.Items; + + Assert.AreEqual("SearchMatch", items.ToString()); + } + } +} 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..1bc90d0866630fb1d6b44d2f66d6c5f92ee2d932 100644 --- a/source/ProtocolGenerator/Command.cs +++ b/source/ProtocolGenerator/Command.cs @@ -1,8 +1,12 @@ -using System.Collections.ObjectModel; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Text; +using System.Linq; +using System; namespace MasterDevs.ChromeDevTools.ProtocolGenerator { - class Command : ProtocolItem + public class Command : ProtocolItem { public Command() { @@ -23,6 +27,9 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator set; } + /// <remarks> + /// This property is currently ignored. + /// </remarks> public Collection<string> Handlers { get; @@ -46,5 +53,101 @@ 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.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.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(); + } + + public Property GetParameter(string name) + { + return this.Parameters.SingleOrDefault(p => string.Equals(p.Name, name, StringComparison.OrdinalIgnoreCase)); + } } } diff --git a/source/ProtocolGenerator/Domain.cs b/source/ProtocolGenerator/Domain.cs index 248f6b132fc68c3a61512b48c844609d40365e3c..a707947291ead3d5f658dbf253806220c0e99ab8 100644 --- a/source/ProtocolGenerator/Domain.cs +++ b/source/ProtocolGenerator/Domain.cs @@ -1,9 +1,11 @@ using Newtonsoft.Json; +using System; using System.Collections.ObjectModel; +using System.Linq; namespace MasterDevs.ChromeDevTools.ProtocolGenerator { - class Domain : ProtocolItem + public class Domain : ProtocolItem { public Domain() { @@ -48,5 +50,15 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator get; set; } + + public Command GetCommand(string name) + { + return this.Commands.SingleOrDefault(c => string.Equals(c.Name, name, StringComparison.OrdinalIgnoreCase)); + } + + public Type GetType(string name) + { + return this.Types.SingleOrDefault(t => string.Equals(t.Name, name, StringComparison.OrdinalIgnoreCase)); + } } } diff --git a/source/ProtocolGenerator/Event.cs b/source/ProtocolGenerator/Event.cs index 557661197ed846d882bea88dadd16e980c859750..2456dc94e67fcaace2dd87c8fabf9cedf7230380 100644 --- a/source/ProtocolGenerator/Event.cs +++ b/source/ProtocolGenerator/Event.cs @@ -2,7 +2,7 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator { - class Event : ProtocolItem + public class Event : ProtocolItem { public Event() { diff --git a/source/ProtocolGenerator/MasterDevs.ChromeDevTools.ProtocolGenerator.csproj b/source/ProtocolGenerator/MasterDevs.ChromeDevTools.ProtocolGenerator.csproj index 4a58f80391dbf58d9e10dd4e977a50dc697846f2..fc1147ccef27175b3f20564cdb898c1e3800d7b0 100644 --- a/source/ProtocolGenerator/MasterDevs.ChromeDevTools.ProtocolGenerator.csproj +++ b/source/ProtocolGenerator/MasterDevs.ChromeDevTools.ProtocolGenerator.csproj @@ -50,14 +50,18 @@ <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="ProtocolProcessor.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..e79082f11b98ea3af39ef7f0f200fea1e197c693 --- /dev/null +++ b/source/ProtocolGenerator/NameEqualityComparer.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MasterDevs.ChromeDevTools.ProtocolGenerator +{ + class NameEqualityComparer<T> : EqualityComparer<T> + where T : ProtocolItem + { + public static NameEqualityComparer<T> Instance + { get; } = new NameEqualityComparer<T>(); + + public override bool Equals(T x, T y) + { + if (x == null || y == null) + { + return false; + } + + return string.Equals(x.Name, y.Name, StringComparison.OrdinalIgnoreCase); + } + + public override int GetHashCode(T 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..3a577f4c716d3d391cb3eccfb9c037a40cc4dfdf 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,43 @@ 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) - { - string json = File.ReadAllText(path); - JsonSerializerSettings settings = new JsonSerializerSettings(); - settings.MissingMemberHandling = MissingMemberHandling.Error; - settings.MetadataPropertyHandling = MetadataPropertyHandling.Ignore; - Protocol p = JsonConvert.DeserializeObject<Protocol>(json, settings); - return p; - } - private static void Main(string[] args) { - var filePath = "protocol.json"; - var protocolObject = LoadProtocol(filePath); + // 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-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>(); + + // "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, explicitMappings); + protocols.Add(p); + } + + Protocol protocolObject = new Protocol(); + foreach(var protocol in protocols) + { + ProtocolMerger.Merge(protocol, protocolObject); + } var outputFolder = "OutputProtocol"; if (args.Length > 0) @@ -79,9 +103,9 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator { var propertyType = type.Kind; var typeName = type.Name; - if (type.Enum.Any() - || type.Properties.Any() - || "object" == propertyType) + if (type.IsEnum() + || type.IsClass() + || type.IsObject()) { propertyType = domain + "." + typeName; } @@ -183,10 +207,10 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator var parameters = evnt.Parameters; // ignoreing "handlers" ... i'm not sure what they are for yet _DomainEvents[domainDirectoryInfo.Name].Add(eventName); - WriteEvent(domainDirectoryInfo, eventName, description, parameters); + WriteEvent(domainDirectoryInfo, eventName, description, parameters, evnt.SupportedBy); } - private static void WriteEvent(DirectoryInfo domainDirectoryInfo, string eventName, string description, IEnumerable<Property> parameters) + private static void WriteEvent(DirectoryInfo domainDirectoryInfo, string eventName, string description, IEnumerable<Property> parameters, IEnumerable<string> supportedBy) { var className = ToCamelCase(eventName) + EventSubclass; var sb = new StringBuilder(); @@ -205,6 +229,7 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator } sb.AppendFormat("\t[{0}({1}.{2}.{3})]", EventAttribute, ProtocolNameClass, domainDirectoryInfo.Name, ToCamelCase(eventName)); sb.AppendLine(); + WriteSupportedBy(sb, supportedBy); sb.AppendFormat("\tpublic class {0}", className); sb.AppendLine(); sb.AppendLine("\t{"); @@ -225,11 +250,11 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator var parameters = command.Parameters; var returnObject = command.Returns; _DomainCommands[domainDirectoryInfo.Name].Add(commandName); - WriteCommand(domainDirectoryInfo, commandName, description, parameters); - WriteCommandResponse(domainDirectoryInfo, commandName, description, returnObject); + WriteCommand(domainDirectoryInfo, commandName, description, parameters, command.SupportedBy); + WriteCommandResponse(domainDirectoryInfo, commandName, description, returnObject, command.SupportedBy); } - private static void WriteCommandResponse(DirectoryInfo domainDirectoryInfo, string commandName, string description, IEnumerable<Property> returnObject) + private static void WriteCommandResponse(DirectoryInfo domainDirectoryInfo, string commandName, string description, IEnumerable<Property> returnObject, IEnumerable<string> supportedBy) { var className = ToCamelCase(commandName) + CommandResponseSubclass; var sb = new StringBuilder(); @@ -249,6 +274,7 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator } sb.AppendFormat("\t[{0}({1}.{2}.{3})]", CommandResponseAttribute, ProtocolNameClass, domainDirectoryInfo.Name, ToCamelCase(commandName)); sb.AppendLine(); + WriteSupportedBy(sb, supportedBy); sb.AppendFormat("\tpublic class {0}", className); sb.AppendLine(); sb.AppendLine("\t{"); @@ -261,7 +287,7 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator WriteToFile(domainDirectoryInfo, className, sb.ToString()); } - private static void WriteCommand(DirectoryInfo domainDirectoryInfo, string commandName, string description, IEnumerable<Property> parameters) + private static void WriteCommand(DirectoryInfo domainDirectoryInfo, string commandName, string description, IEnumerable<Property> parameters, IEnumerable<string> supportedBy) { var className = ToCamelCase(commandName) + CommandSubclass; var sb = new StringBuilder(); @@ -282,6 +308,7 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator } sb.AppendFormat("\t[{0}({1}.{2}.{3})]", CommandAttribute, ProtocolNameClass, domainDirectoryInfo.Name, ToCamelCase(commandName)); sb.AppendLine(); + WriteSupportedBy(sb, supportedBy); sb.AppendFormat("\tpublic class {0}", className); sb.AppendLine(); sb.AppendLine("\t{"); @@ -324,6 +351,7 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator sb.AppendFormat("\t/// {0}", type.Description); sb.AppendLine(); sb.AppendLine("\t/// </summary>"); + WriteSupportedBy(sb, type); sb.AppendFormat("\tpublic class {0}", className); sb.AppendLine(); sb.AppendLine("\t{"); @@ -454,6 +482,7 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator sb.AppendFormat("\t/// {0}", type.Description); sb.AppendLine(); sb.AppendLine("\t/// </summary>"); + WriteSupportedBy(sb, type); sb.AppendFormat("\tpublic enum {0}", enumName); sb.AppendLine(); sb.AppendLine("\t{"); @@ -467,6 +496,19 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator WriteToFile(domainDirectoryInfo, enumName, sb.ToString()); } + private static void WriteSupportedBy(StringBuilder sb, ProtocolItem type) + { + WriteSupportedBy(sb, type.SupportedBy); + } + + private static void WriteSupportedBy(StringBuilder sb, IEnumerable<string> supportedBy) + { + foreach(var browser in supportedBy) + { + sb.AppendLine($"\t[SupportedBy(\"{browser}\")"); + } + } + private static void WriteToFile(DirectoryInfo domainDirectoryInfo, string fileName, string fileContents) { var fullPath = Path.Combine(domainDirectoryInfo.FullName, fileName + ".cs"); diff --git a/source/ProtocolGenerator/Property.cs b/source/ProtocolGenerator/Property.cs index 7645385ba81b78ed4611337f92ddccc4bf00f6d0..9002cadf8e2aca6267369b3cb830540bab33b4df 100644 --- a/source/ProtocolGenerator/Property.cs +++ b/source/ProtocolGenerator/Property.cs @@ -2,7 +2,7 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator { - class Property : Type + public class Property : Type { [JsonProperty("name")] public override string Name diff --git a/source/ProtocolGenerator/Protocol.cs b/source/ProtocolGenerator/Protocol.cs index ae206ed86f9019041adf5f86c381dc4faa1895e3..1f5ff07a73dd3593c4dc464a322093524c1f3fac 100644 --- a/source/ProtocolGenerator/Protocol.cs +++ b/source/ProtocolGenerator/Protocol.cs @@ -1,9 +1,16 @@ using System.Collections.ObjectModel; +using System.Linq; namespace MasterDevs.ChromeDevTools.ProtocolGenerator { - class Protocol + public class Protocol { + public Protocol() + { + this.Compatible = new Collection<string>(); + this.Domains = new Collection<Domain>(); + } + public Collection<string> Compatible { get; @@ -21,5 +28,34 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator get; set; } + + public string SourceFile + { + get; + set; + } + + public string Alias + { + get; + set; + } + + public Domain GetDomain(string name) + { + return this.Domains.SingleOrDefault(d => string.Equals(d.Name, name, System.StringComparison.OrdinalIgnoreCase)); + } + + public override string ToString() + { + if(this.SourceFile != null) + { + return $"{this.Alias} ({this.SourceFile})"; + } + else + { + return this.Alias; + } + } } } diff --git a/source/ProtocolGenerator/ProtocolItem.cs b/source/ProtocolGenerator/ProtocolItem.cs index 61bae95f698cfcfecdfb486507599265f205e729..3da9daf6ee0e419108eee94f77cc44ad9fc7ca5e 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 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..b28270c05d19f0a34272a8ea4ebf22e55a4eec19 --- /dev/null +++ b/source/ProtocolGenerator/ProtocolMerger.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +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<Domain>.Instance)) + { + target.Domains.Add(domain); + } + else + { + Merge(source, domain, target.Domains.Single(t => NameEqualityComparer<Domain>.Instance.Equals(domain, t))); + } + } + } + + static void Merge(Protocol protocol, Domain source, Domain target) + { + Merge(protocol, source, source.Commands, target.Commands); + Merge(protocol, source, source.Events, target.Events); + Merge(protocol, source, source.Types, target.Types); + } + + static void Merge<T>(Protocol protocol, Domain domain, Collection<T> source, Collection<T> target) + where T : ProtocolItem + { + foreach (var item in source) + { + if (!target.Contains(item, NameEqualityComparer<T>.Instance)) + { + target.Add(item); + } + else + { + var targetItem = target.Single(t => NameEqualityComparer<T>.Instance.Equals(item, t)); + + if (!targetItem.Equals(item)) + { + Console.WriteLine($"{protocol.Alias};{domain.Name};{item.Name};{item};{targetItem};{typeof(T).Name}"); + } + else + { + foreach (var v in item.SupportedBy) + { + targetItem.SupportedBy.Add(v); + } + } + } + } + } + } +} diff --git a/source/ProtocolGenerator/ProtocolProcessor.cs b/source/ProtocolGenerator/ProtocolProcessor.cs new file mode 100644 index 0000000000000000000000000000000000000000..2286424ad44295645d84ee2932fa53e860bae2e2 --- /dev/null +++ b/source/ProtocolGenerator/ProtocolProcessor.cs @@ -0,0 +1,122 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MasterDevs.ChromeDevTools.ProtocolGenerator +{ + public class ProtocolProcessor + { + public static void ResolveTypeReferences(Protocol protocol, Dictionary<string, string> explicitMappings) + { + foreach (var domain in protocol.Domains) + { + ResolveTypeReferences(protocol, domain, explicitMappings); + } + } + + public static void ResolveTypeReferences(Protocol protocol, Domain domain, Dictionary<string, string> explicitMappings) + { + foreach (var command in domain.Commands) + { + ResolveTypeReferences(protocol, domain, command, explicitMappings); + } + } + + public static void ResolveTypeReferences(Protocol protocol, Domain domain, Command command, Dictionary<string, string> explicitMappings) + { + foreach (var parameter in command.Parameters) + { + ResolveTypeReferences(protocol, domain, parameter, explicitMappings); + } + + foreach (var returnValue in command.Returns) + { + ResolveTypeReferences(protocol, domain, returnValue, explicitMappings); + } + } + + public static void ResolveTypeReferences(Protocol protocol, Domain domain, Type property, Dictionary<string, string> explicitMappings) + { + if (property.TypeReference != null) + { + // Find the type which is being referenced + var referenceParts = property.TypeReference.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries); + + Domain referencedDomain = null; + Type referencedType = null; + + if (referenceParts.Length == 1) + { + referencedDomain = domain; + referencedType = domain.GetType(referenceParts[0]); + } + else if (referenceParts.Length == 2) + { + referencedDomain = protocol.GetDomain(referenceParts[0]); + referencedType = referencedDomain.GetType(referenceParts[1]); + } + else + { + throw new ArgumentOutOfRangeException(); + } + + string fullReferenceName = $"{referencedDomain.Name}.{referencedType.Name}"; + + // If it is a string, it can be resolved easily + 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); + } + } + + public 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; + } + } +} \ No newline at end of file diff --git a/source/ProtocolGenerator/Type.cs b/source/ProtocolGenerator/Type.cs index 79c70838ea69b7751fb0a745b6d40946404159a4..7d8f8cfc9850d3fb9b9691e0d5a92b3a14e67bee 100644 --- a/source/ProtocolGenerator/Type.cs +++ b/source/ProtocolGenerator/Type.cs @@ -1,14 +1,17 @@ using Newtonsoft.Json; +using System; +using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; namespace MasterDevs.ChromeDevTools.ProtocolGenerator { - class Type : ProtocolItem + public class Type : ProtocolItem { 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 +21,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 +64,109 @@ 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.TypeName + "[]"; + } + 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; + } + + bool equals = base.Equals(obj); + equals &= string.Equals(this.Kind, other.Kind, StringComparison.OrdinalIgnoreCase); + equals &= this.Enum.SetEquals(other.Enum); + equals &= this.Properties.SetEquals(other.Properties); + equals &= Type.Equals(this.Items, other.Items); + equals &= this.MinItems == other.MinItems; + equals &= this.MaxItems == other.MaxItems; + equals &= string.Equals(this.TypeReference, other.TypeReference, StringComparison.OrdinalIgnoreCase); + + return equals; + } + + 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; + } + } + + public bool IsString() + { + 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(); + } + + public bool IsClass() + { + return this.Properties.Any(); + } + + public bool IsObject() + { + return string.Equals(this.Kind, "object", StringComparison.OrdinalIgnoreCase); + } + + public override string ToString() + { + return this.TypeName; + } } } diff --git a/source/ProtocolGenerator/Version.cs b/source/ProtocolGenerator/Version.cs index b9d6dc8cb2b39cf3fbdee36cfbd12ca6a3664935..64853209e0e1d9b9dd84215952baea09db845ccb 100644 --- a/source/ProtocolGenerator/Version.cs +++ b/source/ProtocolGenerator/Version.cs @@ -1,6 +1,6 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator { - class Version + public class Version { public string Major {