示例#1
0
        public override async Task FinalizeGeneration(ProtocolGeneration proto)
        {
            await base.FinalizeGeneration(proto);

            if (proto.Protocol.Namespace == "Bethesda")
            {
                return;
            }

            bool all = proto.Protocol.Namespace == "All";

            FileGeneration fg = new FileGeneration();

            ObjectGeneration.AddAutogenerationComment(fg);
            fg.AppendLine("using Loqui;");
            fg.AppendLine("using Mutagen.Bethesda.Plugins.Records.Internals;");
            fg.AppendLine();

            using (new NamespaceWrapper(fg, proto.DefaultNamespace, fileScoped: false))
            {
                using (var comment = new CommentWrapper(fg))
                {
                    comment.Summary.AppendLine("A static class to house initialization warmup logic");
                }
                using (var c = new ClassWrapper(fg, $"Warmup{proto.Protocol.Namespace}"))
                {
                    c.Static  = true;
                    c.Partial = true;
                }
                using (new BraceWrapper(fg))
                {
                    using (var comment = new CommentWrapper(fg))
                    {
                        comment.Summary.AppendLine("Will initialize internals in a more efficient way that avoids reflection.");
                        comment.Summary.AppendLine("Not required to call, but can be used to warm up ahead of time.");
                        if (!all)
                        {
                            comment.Summary.AppendLine("<br/><br/>NOTE: Calling this warmup which is for a single game, will require you warm up");
                            comment.Summary.AppendLine("other games in the same fashion.  Use WarmupAll if you want all games to be warmed.");
                        }
                    }
                    using (var args = new FunctionWrapper(fg,
                                                          "public static void Init"))
                    {
                    }
                    using (new BraceWrapper(fg))
                    {
                        if (all)
                        {
                            using (var args = new ArgsWrapper(fg,
                                                              $"Loqui.Initialization.SpinUp"))
                            {
                                args.Add($"new ProtocolDefinition_Bethesda()");
                            }
                            foreach (var otherProto in proto.Gen.Protocols.Values
                                     .Where(p => p.DefaultNamespace.Contains("Mutagen.Bethesda"))
                                     .Where(p => !p.DefaultNamespace.Contains("Mutagen.Bethesda.Plugins.Records"))
                                     .Where(p => !object.ReferenceEquals(p, proto)))
                            {
                                fg.AppendLine($"{otherProto.DefaultNamespace}.Warmup{otherProto.Protocol.Namespace}.Init();");
                            }
                        }
                        else
                        {
                            using (var args = new ArgsWrapper(fg,
                                                              $"Loqui.Initialization.SpinUp"))
                            {
                                args.Add($"new ProtocolDefinition_Bethesda()");
                                args.Add($"new ProtocolDefinition_{proto.Protocol.Namespace}()");
                            }
                            fg.AppendLine($"LinkInterfaceMapping.AutomaticRegistration = false;");
                            using (var args = new ArgsWrapper(fg,
                                                              $"LinkInterfaceMapping.Register"))
                            {
                                args.Add($"new {proto.DefaultNamespace}.Internals.LinkInterfaceMapping()");
                            }
                            fg.AppendLine("InitCustom();");
                        }
                    }

                    fg.AppendLine("static partial void InitCustom();");
                }
            }
            var path = Path.Combine(proto.DefFileLocation.FullName, $"../Warmup{proto.Protocol.Namespace}{Loqui.Generation.Constants.AutogeneratedMarkerString}.cs");

            fg.Generate(path);
            proto.GeneratedFiles.Add(path, ProjItemType.Compile);
        }
        public override async Task PrepareGeneration(ProtocolGeneration proto)
        {
            await base.PrepareGeneration(proto);

            // Compile interfaces implementing interfaces mapping data
            var interfaceInheritenceMappings = new Dictionary <string, HashSet <string> >();

            foreach (var obj in proto.ObjectGenerationsByID.Values)
            {
                foreach (var item in obj.Node.Elements(XName.Get("LinkInterface", LoquiGenerator.Namespace)))
                {
                    ObjectMappings.GetOrAdd(proto.Protocol).GetOrAdd(item.Value).Add(obj);
                }
            }

            // Generate interface files themselves
            if (!ObjectMappings.TryGetValue(proto.Protocol, out var mappings))
            {
                return;
            }
            foreach (var interf in mappings)
            {
                FileGeneration fg = new FileGeneration();
                ObjectGeneration.AddAutogenerationComment(fg);

                fg.AppendLine("using Mutagen.Bethesda;");
                fg.AppendLine();

                var implementedObjs = new HashSet <ObjectGeneration>();

                void AddObjs(string interfKey)
                {
                    implementedObjs.Add(ObjectMappings[proto.Protocol][interfKey]);
                    if (interfaceInheritenceMappings.TryGetValue(interfKey, out var parents))
                    {
                        foreach (var parent in parents)
                        {
                            AddObjs(parent);
                        }
                    }
                }

                AddObjs(interf.Key);

                using (new NamespaceWrapper(fg, proto.DefaultNamespace, fileScoped: false))
                {
                    fg.AppendLine("/// <summary>");
                    fg.AppendLine($"/// Implemented by: [{string.Join(", ", implementedObjs.Select(o => o.ObjectName))}]");
                    fg.AppendLine("/// </summary>");
                    using (var c = new ClassWrapper(fg, interf.Key))
                    {
                        c.Type = ClassWrapper.ObjectType.@interface;
                        c.Interfaces.Add($"I{proto.Protocol.Namespace}MajorRecordInternal");
                        c.Interfaces.Add($"{interf.Key}Getter");
                        if (interfaceInheritenceMappings.TryGetValue(interf.Key, out var impls))
                        {
                            c.Interfaces.Add(impls);
                        }
                        c.Partial = true;
                    }
                    using (new BraceWrapper(fg))
                    {
                    }
                    fg.AppendLine();

                    fg.AppendLine("/// <summary>");
                    fg.AppendLine($"/// Implemented by: [{string.Join(", ", implementedObjs.Select(o => o.ObjectName))}]");
                    fg.AppendLine("/// </summary>");
                    using (var c = new ClassWrapper(fg, $"{interf.Key}Getter"))
                    {
                        c.Type = ClassWrapper.ObjectType.@interface;
                        c.Interfaces.Add($"I{proto.Protocol.Namespace}MajorRecordGetter");
                        if (interfaceInheritenceMappings.TryGetValue(interf.Key, out var impls))
                        {
                            c.Interfaces.Add(impls.Select(i => $"{i}Getter"));
                        }
                        c.Partial = true;
                    }
                    using (new BraceWrapper(fg))
                    {
                    }
                }

                var path = Path.Combine(proto.DefFileLocation.FullName, $"../Interfaces/{interf.Key}{Loqui.Generation.Constants.AutogeneratedMarkerString}.cs");
                fg.Generate(path);
                proto.GeneratedFiles.Add(path, ProjItemType.Compile);
            }

            // Generate interface to major record mapping registry
            FileGeneration mappingGen = new FileGeneration();

            ObjectGeneration.AddAutogenerationComment(mappingGen);
            mappingGen.AppendLine($"using System;");
            mappingGen.AppendLine($"using System.Collections.Generic;");
            mappingGen.AppendLine($"using Mutagen.Bethesda.Plugins.Records.Internals;");
            mappingGen.AppendLine();
            using (new NamespaceWrapper(mappingGen, $"{proto.DefaultNamespace}.Internals", fileScoped: false))
            {
                using (var c = new ClassWrapper(mappingGen, "LinkInterfaceMapping"))
                {
                    c.Interfaces.Add(nameof(ILinkInterfaceMapping));
                }
                using (new BraceWrapper(mappingGen))
                {
                    mappingGen.AppendLine($"public IReadOnlyDictionary<Type, Type[]> InterfaceToObjectTypes {{ get; }}");
                    mappingGen.AppendLine();
                    mappingGen.AppendLine($"public {nameof(GameCategory)} GameCategory => {nameof(GameCategory)}.{proto.Protocol.Namespace};");
                    mappingGen.AppendLine();

                    mappingGen.AppendLine("public LinkInterfaceMapping()");
                    using (new BraceWrapper(mappingGen))
                    {
                        mappingGen.AppendLine($"var dict = new Dictionary<Type, Type[]>();");
                        foreach (var interf in mappings)
                        {
                            mappingGen.AppendLine($"dict[typeof({interf.Key})] = new Type[]");
                            using (new BraceWrapper(mappingGen)
                            {
                                AppendSemicolon = true
                            })
                            {
                                foreach (var obj in interf.Value)
                                {
                                    mappingGen.AppendLine($"typeof({obj.ObjectName}),");
                                }
                            }
                            mappingGen.AppendLine($"dict[typeof({interf.Key}Getter)] = dict[typeof({interf.Key})];");
                        }

                        mappingGen.AppendLine($"InterfaceToObjectTypes = dict;");
                    }
                }
            }
            mappingGen.AppendLine();
            var mappingPath = Path.Combine(proto.DefFileLocation.FullName, $"../Interfaces/LinkInterfaceMapping{Loqui.Generation.Constants.AutogeneratedMarkerString}.cs");

            mappingGen.Generate(mappingPath);
            proto.GeneratedFiles.Add(mappingPath, ProjItemType.Compile);
        }