public void ProcessTypes(IEnumerable <TypeDefinition> types) { if (types.Any(x => x.Name == "IProtoBuf")) { Console.WriteLine("detected SilentOrbit protos"); processor = new SilentOrbitTypeProcessor(); } else { // We could detect based on subclassing GeneratedMessage*, but no // point unless we have more than 2 types of protogens. Console.WriteLine("assuming Google protos"); processor = new GoogleTypeProcessor(); } foreach (var type in types) { processor.Process(type); } processor.Complete(); // A map from typename to message: var allMessages = new Dictionary <string, MessageNode>(); // Add child nodes to their parents: foreach (var nodeList in processor.PackageNodes.Values) { var children = new List <ILanguageNode>(); var messages = nodeList.Where(x => x is MessageNode).Select(x => x as MessageNode); foreach (var message in messages) { allMessages.Add(message.Name.Text, message); } var enums = nodeList.Where(x => x is EnumNode).Select(x => x as EnumNode); foreach (var node in messages.Where(n => n.Name.Name.Contains("."))) { var parentName = node.Name.Name; parentName = parentName.Substring(0, parentName.LastIndexOf('.')); var parent = messages.First(m => m.Name.Name == parentName); parent.Messages.Add(node); children.Add(node); } foreach (var node in enums.Where(n => n.Name.Name.Contains("."))) { var parentName = node.Name.Name; parentName = parentName.Substring(0, parentName.LastIndexOf('.')); var parent = messages.First(m => m.Name.Name == parentName); parent.Enums.Add(node); children.Add(node); } foreach (var node in children) { nodeList.Remove(node); } } // Move extensions to their sources: var blacklistedExtensionSources = new[] { // These types aren't allowed to have extensions, because they were // made by an intern or something: ".PegasusShared.ScenarioDbRecord" }; foreach (var nodeList in processor.PackageNodes.Values) { var messages = nodeList .Where(x => x is MessageNode) .Select(x => x as MessageNode) .Where(x => !blacklistedExtensionSources.Contains(x.Name.Text)); foreach (var message in messages) { var extensions = message.Fields .Where(x => x.Label != FieldLabel.Required && x.Tag >= 100 && !blacklistedExtensionSources.Contains(x.TypeName.Text)) .ToList(); foreach (var extField in extensions) { message.Fields.Remove(extField); message.AcceptsExtensions = true; var target = message.Name; var source = extField.TypeName; if (String.IsNullOrEmpty(source.Package)) { throw new Exception("extension field is not a message"); } var sourceNode = allMessages[source.Text]; sourceNode.AddExtend(target, extField); } } } // A map from type name to its file var typesMap = new Dictionary <string, string>(); var currAssembly = Assembly.GetExecutingAssembly(); var typesMapName = currAssembly.GetManifestResourceNames()[0]; using (var typesMapFile = currAssembly.GetManifestResourceStream(typesMapName)) using (var typesMapReader = new StreamReader(typesMapFile)) { while (!typesMapReader.EndOfStream) { var line = typesMapReader.ReadLine().Trim(); if (line.Length == 0) { continue; } if (line[0] == '#') { continue; } var parts = line.Split(new[] { "\t" }, StringSplitOptions.RemoveEmptyEntries); typesMap[parts[1]] = parts[0]; } } foreach (var nodeList in processor.PackageNodes.Values) { var first = nodeList.First(); var firstType = default(TypeName); if (first is MessageNode) { firstType = (first as MessageNode).Name; } if (first is EnumNode) { firstType = (first as EnumNode).Name; } var firstTypeName = firstType.Text; if (!typesMap.ContainsKey(firstTypeName)) { throw new Exception(String.Format( "Couldn't find the first type of a package in the type map: {0}", firstTypeName)); } var fileName = typesMap[firstTypeName]; var fileNode = new FileNode(fileName, firstType.Package); fileNodes[fileName] = fileNode; var onFirst = true; foreach (var node in nodeList) { var type = default(TypeName); if (node is MessageNode) { type = (node as MessageNode).Name; } if (node is EnumNode) { type = (node as EnumNode).Name; } var typeName = type.Text; if (!onFirst && typesMap.ContainsKey(typeName)) { fileName = typesMap[typeName]; fileNode = new FileNode(fileName, type.Package); fileNodes[fileName] = fileNode; } fileNode.Types.Add(node); messageFile[type.Text] = fileName; onFirst = false; } } }
public void ProcessTypes(IEnumerable <TypeDefinition> types, string typesMapFile) { if (types.Any(x => x.Name == "IProtoBuf" || x.Name == "ServiceDescriptor")) { Console.WriteLine("detected SilentOrbit protos"); processor = new SilentOrbitTypeProcessor(); } else { // We could detect based on subclassing GeneratedMessage*, but no // point unless we have more than 2 types of protogens. Console.WriteLine("assuming Google protos"); processor = new GoogleTypeProcessor(); } foreach (var type in types) { processor.Process(type); } processor.Complete(); // A map from typename to message: var allMessages = new Dictionary <string, MessageNode>(); // Add child nodes to their parents: foreach (var nodeList in processor.PackageNodes.Values) { var children = new List <ILanguageNode>(); var messages = nodeList.Where(x => x is MessageNode).Select(x => x as MessageNode); foreach (var message in messages) { allMessages.Add(message.Name.Text, message); } var enums = nodeList.Where(x => x is EnumNode).Select(x => x as EnumNode); foreach (var node in messages.Where(n => n.Name.Name.Contains("."))) { var parentName = node.Name.Name; parentName = parentName.Substring(0, parentName.LastIndexOf('.')); var parent = messages.First(m => m.Name.Name == parentName); parent.Messages.Add(node); children.Add(node); } foreach (var node in enums.Where(n => n.Name.Name.Contains("."))) { var parentName = node.Name.Name; parentName = parentName.Substring(0, parentName.LastIndexOf('.')); var parent = messages.First(m => m.Name.Name == parentName); parent.Enums.Add(node); children.Add(node); } foreach (var node in children) { nodeList.Remove(node); } } // Move extensions to their sources: var blacklistedExtensionSources = new[] { // These types aren't allowed to have extensions, because they were // made by an intern or something: ".PegasusShared.ScenarioDbRecord" }; foreach (var nodeList in processor.PackageNodes.Values) { var messages = nodeList .Where(x => x is MessageNode) .Select(x => x as MessageNode) .Where(x => !blacklistedExtensionSources.Contains(x.Name.Text)); foreach (var message in messages) { var extensions = message.Fields .Where(x => x.Label != FieldLabel.Required && x.Tag >= 100 && !blacklistedExtensionSources.Contains(x.TypeName.Text)) .ToList(); foreach (var extField in extensions) { message.Fields.Remove(extField); message.AcceptsExtensions = true; message.ExtendLowerBound = Math.Min(message.ExtendLowerBound, extField.Tag); message.ExtendUpperBound = Math.Max(message.ExtendUpperBound, extField.Tag); var target = message.Name; var source = extField.TypeName; // Extensions which are primitive types if (String.IsNullOrEmpty(source.Package)) { message.AddExtend(target, extField); } // Extensions which are messages in other files else { var sourceNode = allMessages[source.Text]; sourceNode.AddExtend(target, extField); } } } } // A map from type name to its file var typesMap = new Dictionary <string, string>(); using (var typesMapReader = new StreamReader(typesMapFile)) { while (!typesMapReader.EndOfStream) { var line = typesMapReader.ReadLine().Trim(); if (line.Length == 0) { continue; } if (line[0] == '#') { continue; } var parts = line.Split(new[] { "\t" }, StringSplitOptions.RemoveEmptyEntries); typesMap[parts[1]] = parts[0]; } } foreach (var nodeList in processor.PackageNodes.Values) { string fileName = null; FileNode fileNode = null; foreach (var node in nodeList) { var type = default(TypeName); if (node is MessageNode) { type = (node as MessageNode).Name; } if (node is ServiceNode) { type = (node as ServiceNode).Name; } if (node is EnumNode) { type = (node as EnumNode).Name; } var typeName = type.Text; if (typesMap.ContainsKey(typeName)) { fileName = typesMap[typeName]; if (fileNodes.ContainsKey(fileName)) { fileNode = fileNodes[fileName]; } else { fileNode = new FileNode(fileName, type.Package); fileNodes[fileName] = fileNode; } } else if (fileNode == null) { throw new Exception(String.Format( "Couldn't find the first type of a package in the type map: {0}", typeName)); } fileNode.Types.Add(node); messageFile[type.Text] = fileName; } } // Define "method_id" extension for identifying RPC methods. var methodIdExtension = new ExtendNode(new TypeName( "google.protobuf", "MethodOptions")); methodIdExtension.Fields.Add(new FieldNode( "method_id", FieldLabel.Optional, FieldType.UInt32, 50000)); fileNodes["bnet/rpc"].Types.Add(methodIdExtension); }