Example #1
0
    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;
            }
        }
    }
Example #2
0
    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);
    }