Skip to content
Snippets Groups Projects
Commit 606abc78 authored by Frederik Carlier's avatar Frederik Carlier
Browse files

Merging protocols:

- First logic to merge two protocols into a single one
- Support resolving types for command parameters
parent 72685af6
No related branches found
No related tags found
No related merge requests found
Showing
with 414 additions and 52 deletions

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.Inspector10)]
[DeploymentItem(DeploymentItems.Protocol)]
public void EqualsTest()
{
var inspector10 = ProtocolProcessor.LoadProtocol(DeploymentItems.Inspector10, "inspector-1.0");
var protocol = ProtocolProcessor.LoadProtocol(DeploymentItems.Protocol, "protocol");
ProtocolProcessor.ResolveTypeReferences(inspector10);
ProtocolProcessor.ResolveTypeReferences(protocol);
var searchInResource10 = inspector10.GetDomain("Page").GetCommand("searchInResource");
var searchInResourceTip = protocol.GetDomain("Page").GetCommand("searchInResource");
// Quick fact check: both methods have the same string equivalent,
// ([] result) searchInResource(string frameId, string url, string query, boolean caseSensitive, boolean isRegex)
Assert.AreEqual<string>(searchInResource10.ToString(), searchInResourceTip.ToString());
// The result is a type, check whether the type has the same properties
var result10 = searchInResource10.Returns.Single();
var resultTip = searchInResourceTip.Returns.Single();
Assert.IsTrue(result10.Equals(resultTip));
Assert.IsTrue(searchInResource10.Equals(searchInResourceTip));
Assert.IsTrue(searchInResourceTip.Equals(searchInResource10));
}
}
}
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 Protocol = "protocol.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" />
</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\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 Microsoft.VisualStudio.TestTools.UnitTesting;
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 ResolveTypeReferencesTest()
{
Protocol p = ProtocolProcessor.LoadProtocol(DeploymentItems.Inspector10, "Chrome-1.0");
ProtocolProcessor.ResolveTypeReferences(p);
var evaluateCommand = p.GetDomain("Runtime").GetCommand("evaluate");
var frameIdParameter = evaluateCommand.GetParameter("frameId");
Assert.AreEqual("string", frameIdParameter.TypeName);
}
}
}
......@@ -2,10 +2,11 @@
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()
{
......@@ -142,5 +143,10 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator
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()
{
......
......@@ -61,6 +61,7 @@
<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>
......
......@@ -24,36 +24,6 @@ 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 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)
{
......@@ -71,7 +41,9 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator
foreach(var protocolFile in protocolFiles)
{
protocols.Add(LoadProtocol(protocolFile.Value, protocolFile.Key));
Protocol p = ProtocolProcessor.LoadProtocol(protocolFile.Value, protocolFile.Key);
ProtocolProcessor.ResolveTypeReferences(p);
protocols.Add(p);
}
Protocol protocolObject = new Protocol();
......@@ -121,9 +93,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;
}
......
......@@ -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()
{
......@@ -39,5 +40,22 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator
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;
}
}
}
}
......@@ -4,7 +4,7 @@ using System.Collections.ObjectModel;
namespace MasterDevs.ChromeDevTools.ProtocolGenerator
{
abstract class ProtocolItem
public abstract class ProtocolItem
{
public ProtocolItem()
{
......
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)
{
foreach (var domain in protocol.Domains)
{
ResolveTypeReferences(protocol, domain);
}
}
public static void ResolveTypeReferences(Protocol protocol, Domain domain)
{
foreach (var command in domain.Commands)
{
ResolveTypeReferences(protocol, domain, command);
}
}
public static void ResolveTypeReferences(Protocol protocol, Domain domain, Command command)
{
foreach (var parameter in command.Parameters)
{
ResolveTypeReferences(protocol, domain, parameter);
}
foreach (var returnValue in command.Returns)
{
ResolveTypeReferences(protocol, domain, returnValue);
}
}
public static void ResolveTypeReferences(Protocol protocol, Domain domain, Property property)
{
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();
}
// If it is a string, it can be resolved easily
if(referencedType.IsString())
{
property.Kind = "string";
property.TypeReference = null;
}
}
}
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
......@@ -2,10 +2,11 @@
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()
{
......@@ -95,14 +96,16 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator
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);
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()
......@@ -135,5 +138,25 @@ namespace MasterDevs.ChromeDevTools.ProtocolGenerator
return hash;
}
}
public bool IsString()
{
return string.Equals(this.Kind, "string", 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);
}
}
}
namespace MasterDevs.ChromeDevTools.ProtocolGenerator
{
class Version
public class Version
{
public string Major
{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment