Skip to content
Snippets Groups Projects
Commit d36f44b3 authored by Kevin Prudente's avatar Kevin Prudente
Browse files

Merge pull request #3 from quamotion/features/multiversion-merge

[RFC] Supporting multiple versions of the Chrome Debugger Protocol
parents c02c8f34 f093be9f
No related branches found
No related tags found
No related merge requests found
Showing
with 763 additions and 30 deletions
......@@ -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}" />
......
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;
}
}
}

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
......
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));
}
}
}
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";
}
}
<?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
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")]
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);
}
}
}
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());
}
}
}
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;
}
}
}
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));
}
}
}
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));
}
}
}
......@@ -2,7 +2,7 @@
namespace MasterDevs.ChromeDevTools.ProtocolGenerator
{
class Event : ProtocolItem
public class Event : ProtocolItem
{
public Event()
{
......
......@@ -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>
......
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);
}
}
}
......@@ -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)
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-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)
{
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;
Protocol p = ProtocolProcessor.LoadProtocol(protocolFile.Value, protocolFile.Key);
ProtocolProcessor.ResolveTypeReferences(p, explicitMappings);
protocols.Add(p);
}
private static void Main(string[] args)
Protocol protocolObject = new Protocol();
foreach(var protocol in protocols)
{
var filePath = "protocol.json";
var protocolObject = LoadProtocol(filePath);
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");
......
......@@ -2,7 +2,7 @@
namespace MasterDevs.ChromeDevTools.ProtocolGenerator
{
class Property : Type
public class Property : Type
{
[JsonProperty("name")]
public override string Name
......
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;
}
}
}
}
namespace MasterDevs.ChromeDevTools.ProtocolGenerator
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace MasterDevs.ChromeDevTools.ProtocolGenerator
{
public abstract class ProtocolItem
{
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;
}
}
}
}
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);
}
}
}
}
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment