Ejemplo n.º 1
0
        public override async Task FinalizeGeneration(ProtocolGeneration proto)
        {
            await base.FinalizeGeneration(proto);

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

            FileGeneration fg = new FileGeneration();

            fg.AppendLine("using System;");
            fg.AppendLine();

            using (new NamespaceWrapper(fg, "Mutagen.Bethesda"))
            {
                using (var cl = new ClassWrapper(fg, "GameCategoryHelper"))
                {
                    cl.Partial = true;
                    cl.Static  = true;
                }
                using (new BraceWrapper(fg))
                {
                    using (var args = new FunctionWrapper(fg,
                                                          $"public static {nameof(GameCategory)} FromModType<TMod>"))
                    {
                        args.Wheres.Add($"where TMod : {nameof(IModGetter)}");
                    }
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine("switch (typeof(TMod).Name)");
                        using (new BraceWrapper(fg))
                        {
                            foreach (var cat in EnumExt.GetValues <GameCategory>())
                            {
                                fg.AppendLine($"case \"I{cat}Mod\":");
                                fg.AppendLine($"case \"I{cat}ModGetter\":");
                                using (new DepthWrapper(fg))
                                {
                                    fg.AppendLine($"return {nameof(GameCategory)}.{cat};");
                                }
                            }

                            fg.AppendLine("default:");
                            using (new BraceWrapper(fg))
                            {
                                fg.AppendLine("throw new ArgumentException($\"Unknown game type for: {typeof(TMod).Name}\");");
                            }
                        }
                    }
                }
            }

            var path = Path.Combine(proto.DefFileLocation.FullName, "../Extensions", $"GameCategoryHelper{Loqui.Generation.Constants.AutogeneratedMarkerString}.cs");

            fg.Generate(path);
            proto.GeneratedFiles.Add(path, ProjItemType.Compile);
        }
Ejemplo n.º 2
0
 public Task PrepareGeneration(ProtocolGeneration proto)
 {
     return(Task.WhenAll(
                subModules.Select(
                    (subGen) =>
     {
         return subGen.PrepareGeneration(proto);
     })));
 }
Ejemplo n.º 3
0
        public override async Task FinalizeGeneration(ProtocolGeneration proto)
        {
            await base.FinalizeGeneration(proto);

            if (proto.Protocol.Namespace != "All")
            {
                return;
            }
            await Task.WhenAll(proto.Gen.Protocols.Values.SelectMany(p => p.ObjectGenerationsByID.Values.Select(o => o.LoadingCompleteTask.Task)));

            FileGeneration fg = new FileGeneration();

            foreach (var modObj in mods)
            {
                fg.AppendLine($"using Mutagen.Bethesda.{modObj.ProtoGen.Protocol.Namespace};");
            }
            fg.AppendLine($"using Mutagen.Bethesda.Environments;");
            fg.AppendLine($"using Mutagen.Bethesda.Plugins.Cache;");
            fg.AppendLine();

            using (new NamespaceWrapper(fg, "Mutagen.Bethesda", fileScoped: false))
            {
                using (var c = new ClassWrapper(fg, "GameEnvironmentMixIn"))
                {
                    c.Static = true;
                }
                using (new BraceWrapper(fg))
                {
                    foreach (var modObj in mods)
                    {
                        var relStr  = modObj.GetObjectData().HasMultipleReleases ? $"{modObj.GetObjectData().GameCategory}Release gameRelease" : string.Empty;
                        var retType = $"IGameEnvironmentState<I{modObj.Name}, I{modObj.Name}Getter>";
                        using (var args = new FunctionWrapper(fg,
                                                              $"public static {retType} {modObj.ProtoGen.Protocol.Namespace}"))
                        {
                            args.Add($"this {nameof(GameEnvironment)} env");
                            if (modObj.GetObjectData().HasMultipleReleases)
                            {
                                args.Add(modObj.GetObjectData().HasMultipleReleases ? $"{modObj.GetObjectData().GameCategory}Release gameRelease" : string.Empty);
                            }
                            args.Add($"{nameof(LinkCachePreferences)}? linkCachePrefs = null");
                        }
                        using (new BraceWrapper(fg))
                        {
                            fg.AppendLine($"return env.Construct<I{modObj.Name}, I{modObj.Name}Getter>({(modObj.GetObjectData().HasMultipleReleases ? "gameRelease.ToGameRelease()" : $"GameRelease.{modObj.ProtoGen.Protocol.Namespace}")}, linkCachePrefs);");
Ejemplo n.º 4
0
    public void GenerateCommonXSDForProto(ProtocolGeneration protoGen)
    {
        if (!ShouldGenerateXSD)
        {
            return;
        }
        var      nameSpace = protoGen.Protocol.Namespace;
        XElement root      = new XElement(XSDNamespace + "schema",
                                          new XAttribute("targetNamespace", nameSpace),
                                          new XAttribute("elementFormDefault", "qualified"),
                                          new XAttribute("xmlns", nameSpace),
                                          new XAttribute(XNamespace.Xmlns + "xs", XSDNamespace.NamespaceName));

        foreach (var obj in protoGen.ObjectGenerationsByID.Values)
        {
            foreach (var field in obj.IterateFields())
            {
                if (!TryGetTypeGeneration(field.GetType(), out var xmlGen))
                {
                    throw new ArgumentException("Unsupported type generator: " + field.GetType());
                }
                xmlGen.GenerateForCommonXSD(
                    root,
                    field);
            }
        }

        var outputPath = CommonXSDLocation(protoGen);

        protoGen.GeneratedFiles[outputPath.Path] = ProjItemType.None;
        using (var writer = new XmlTextWriter(outputPath.Path, Encoding.Default))
        {
            writer.Formatting  = Formatting.Indented;
            writer.Indentation = 3;
            XDocument doc = new XDocument(root);
            doc.WriteTo(writer);
        }
        using var streamWriter = File.AppendText(outputPath.Path);
        streamWriter.Write(Environment.NewLine);
    }
Ejemplo n.º 5
0
        public override async Task FinalizeGeneration(ProtocolGeneration proto)
        {
            if (proto.Protocol.Namespace.Equals("Bethesda"))
            {
                return;
            }
            bool           generate = false;
            FileGeneration fg       = new FileGeneration();

            var modObj = proto.ObjectGenerationsByID.Values.FirstOrDefault(o => o.GetObjectType() == ObjectType.Mod);

            fg.AppendLine("using System.Collections.Generic;");
            fg.AppendLine("using Mutagen.Bethesda.Plugins.Cache;");
            fg.AppendLine("using Mutagen.Bethesda.Plugins.Order;");
            fg.AppendLine("using Mutagen.Bethesda.Plugins.Order.Internals;");
            fg.AppendLine();
            using (var n = new NamespaceWrapper(fg, proto.DefaultNamespace))
            {
                using (var c = new ClassWrapper(fg, "TypeOptionSolidifierMixIns"))
                {
                    c.Static = true;
                }
                using (new BraceWrapper(fg))
                {
                    using (new RegionWrapper(fg, "Normal"))
                    {
                        foreach (var obj in proto.ObjectGenerationsByName
                                 .OrderBy(x => x.Key)
                                 .Select(x => x.Value))
                        {
                            if (!await obj.IsMajorRecord())
                            {
                                continue;
                            }

                            var topLevel = modObj.Fields.Any(x =>
                            {
                                if (x is not GroupType grup)
                                {
                                    return(false);
                                }
                                var grupTarget = grup.GetGroupTarget();
                                if (grupTarget == obj)
                                {
                                    return(true);
                                }
                                return(obj.BaseClassTrail().Any(b => b == grupTarget));
                            });
                            var topLevelStr = topLevel ? "TopLevel" : string.Empty;

                            using (var comment = new CommentWrapper(fg))
                            {
                                comment.Summary.AppendLine($"Scope a load order query to {obj.Name}");
                                comment.Parameters.GetOrAdd("listings").AppendLine("ModListings to query");
                                comment.Return.AppendLine($"A typed object to do further queries on {obj.Name}");
                            }
                            using (var args = new FunctionWrapper(fg,
                                                                  $"public static {topLevelStr}TypedLoadOrderAccess<I{proto.Protocol.Namespace}Mod, I{proto.Protocol.Namespace}ModGetter, {obj.Interface(getter: false)}, {obj.Interface(getter: true)}> {obj.Name}"))
                            {
                                args.Add($"this IEnumerable<IModListingGetter<I{proto.Protocol.Namespace}ModGetter>> listings");
                            }
                            using (new BraceWrapper(fg))
                            {
                                using (var args = new ArgsWrapper(fg,
                                                                  $"return new {topLevelStr}TypedLoadOrderAccess<I{proto.Protocol.Namespace}Mod, I{proto.Protocol.Namespace}ModGetter, {obj.Interface(getter: false)}, {obj.Interface(getter: true)}>"))
                                {
                                    args.Add($"(bool includeDeletedRecords) => listings.WinningOverrides<{obj.Interface(getter: true)}>(includeDeletedRecords: includeDeletedRecords)");
                                    args.Add($"({nameof(ILinkCache)} linkCache, bool includeDeletedRecords) => listings.WinningOverrideContexts<I{proto.Protocol.Namespace}Mod, I{proto.Protocol.Namespace}ModGetter, {obj.Interface(getter: false)}, {obj.Interface(getter: true)}>(linkCache, includeDeletedRecords: includeDeletedRecords)");
                                }
                            }
                            fg.AppendLine();

                            using (var comment = new CommentWrapper(fg))
                            {
                                comment.Summary.AppendLine($"Scope a load order query to {obj.Name}");
                                comment.Parameters.GetOrAdd("mods").AppendLine("Mods to query");
                                comment.Return.AppendLine($"A typed object to do further queries on {obj.Name}");
                            }
                            using (var args = new FunctionWrapper(fg,
                                                                  $"public static {topLevelStr}TypedLoadOrderAccess<I{proto.Protocol.Namespace}Mod, I{proto.Protocol.Namespace}ModGetter, {obj.Interface(getter: false)}, {obj.Interface(getter: true)}> {obj.Name}"))
                            {
                                args.Add($"this IEnumerable<I{proto.Protocol.Namespace}ModGetter> mods");
                            }
                            using (new BraceWrapper(fg))
                            {
                                using (var args = new ArgsWrapper(fg,
                                                                  $"return new {topLevelStr}TypedLoadOrderAccess<I{proto.Protocol.Namespace}Mod, I{proto.Protocol.Namespace}ModGetter, {obj.Interface(getter: false)}, {obj.Interface(getter: true)}>"))
                                {
                                    args.Add($"(bool includeDeletedRecords) => mods.WinningOverrides<{obj.Interface(getter: true)}>(includeDeletedRecords: includeDeletedRecords)");
                                    args.Add($"({nameof(ILinkCache)} linkCache, bool includeDeletedRecords) => mods.WinningOverrideContexts<I{proto.Protocol.Namespace}Mod, I{proto.Protocol.Namespace}ModGetter, {obj.Interface(getter: false)}, {obj.Interface(getter: true)}>(linkCache, includeDeletedRecords: includeDeletedRecords)");
                                }
                            }
                            fg.AppendLine();
                            generate = true;
                        }
                    }

                    using (new RegionWrapper(fg, "Link Interfaces"))
                    {
                        if (LinkInterfaceModule.ObjectMappings.TryGetValue(proto.Protocol, out var interfs))
                        {
                            foreach (var interf in interfs)
                            {
                                var getter = $"{interf.Key}Getter";
                                using (var comment = new CommentWrapper(fg))
                                {
                                    comment.Summary.AppendLine($"Scope a load order query to {interf.Key}");
                                    comment.Parameters.GetOrAdd("listings").AppendLine("ModListings to query");
                                    comment.Return.AppendLine($"A typed object to do further queries on {interf.Key}");
                                }
                                using (var args = new FunctionWrapper(fg,
                                                                      $"public static TypedLoadOrderAccess<I{proto.Protocol.Namespace}Mod, I{proto.Protocol.Namespace}ModGetter, {interf.Key}, {getter}> {interf.Key}"))
                                {
                                    args.Add($"this IEnumerable<IModListingGetter<I{proto.Protocol.Namespace}ModGetter>> listings");
                                }
                                using (new BraceWrapper(fg))
                                {
                                    using (var args = new ArgsWrapper(fg,
                                                                      $"return new TypedLoadOrderAccess<I{proto.Protocol.Namespace}Mod, I{proto.Protocol.Namespace}ModGetter, {interf.Key}, {getter}>"))
                                    {
                                        args.Add($"(bool includeDeletedRecords) => listings.WinningOverrides<{getter}>(includeDeletedRecords: includeDeletedRecords)");
                                        args.Add($"({nameof(ILinkCache)} linkCache, bool includeDeletedRecords) => listings.WinningOverrideContexts<I{proto.Protocol.Namespace}Mod, I{proto.Protocol.Namespace}ModGetter, {interf.Key}, {getter}>(linkCache, includeDeletedRecords: includeDeletedRecords)");
                                    }
                                }
                                fg.AppendLine();

                                using (var comment = new CommentWrapper(fg))
                                {
                                    comment.Summary.AppendLine($"Scope a load order query to {interf.Key}");
                                    comment.Parameters.GetOrAdd("mods").AppendLine("Mods to query");
                                    comment.Return.AppendLine($"A typed object to do further queries on {interf.Key}");
                                }
                                using (var args = new FunctionWrapper(fg,
                                                                      $"public static TypedLoadOrderAccess<I{proto.Protocol.Namespace}Mod, I{proto.Protocol.Namespace}ModGetter, {interf.Key}, {getter}> {interf.Key}"))
                                {
                                    args.Add($"this IEnumerable<I{proto.Protocol.Namespace}ModGetter> mods");
                                }
                                using (new BraceWrapper(fg))
                                {
                                    using (var args = new ArgsWrapper(fg,
                                                                      $"return new TypedLoadOrderAccess<I{proto.Protocol.Namespace}Mod, I{proto.Protocol.Namespace}ModGetter, {interf.Key}, {getter}>"))
                                    {
                                        args.Add($"(bool includeDeletedRecords) => mods.WinningOverrides<{getter}>(includeDeletedRecords: includeDeletedRecords)");
                                        args.Add($"({nameof(ILinkCache)} linkCache, bool includeDeletedRecords) => mods.WinningOverrideContexts<I{proto.Protocol.Namespace}Mod, I{proto.Protocol.Namespace}ModGetter, {interf.Key}, {getter}>(linkCache, includeDeletedRecords: includeDeletedRecords)");
                                    }
                                }
                                fg.AppendLine();
                            }
                        }
                    }
                }
            }

            if (!generate)
            {
                return;
            }
            var path = Path.Combine(proto.DefFileLocation.FullName, $"TypeSolidifier{Loqui.Generation.Constants.AutogeneratedMarkerString}.cs");

            fg.Generate(path);
            proto.GeneratedFiles.Add(path, ProjItemType.Compile);
        }
Ejemplo n.º 6
0
 public ClassGeneration(LoquiGenerator gen, ProtocolGeneration protoGen, FilePath sourceFile)
     : base(gen, protoGen, sourceFile)
 {
 }
Ejemplo n.º 7
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);
        }
Ejemplo n.º 8
0
        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);
        }
Ejemplo n.º 9
0
        public override async Task FinalizeGeneration(ProtocolGeneration proto)
        {
            if (proto.Protocol.Namespace.Equals("Bethesda"))
            {
                return;
            }

            var objData = proto.ObjectGenerationsByID.Values.FirstOrDefault()?.GetObjectData();

            if (objData == null)
            {
                return;
            }

            var relString = objData.HasMultipleReleases ? "release.ToGameRelease()" : $"{nameof(GameRelease)}.{proto.Protocol.Namespace}";

            FileGeneration fg = new FileGeneration();

            fg.AppendLine("using System.Collections.Generic;");
            fg.AppendLine($"using Mutagen.Bethesda.Plugins;");
            fg.AppendLine($"using Mutagen.Bethesda.Plugins.Implicit;");
            fg.AppendLine($"using Mutagen.Bethesda.{proto.Protocol.Namespace};");
            fg.AppendLine();
            using (var n = new NamespaceWrapper(fg, "Mutagen.Bethesda"))
            {
                using (var c = new ClassWrapper(fg, "ImplicitsMixIn"))
                {
                    c.Static = true;
                }
                using (new BraceWrapper(fg))
                {
                    using (var args = new FunctionWrapper(fg,
                                                          $"public static IReadOnlyCollection<ModKey> {proto.Protocol.Namespace}"))
                    {
                        args.Add($"this ImplicitBaseMasters _");
                        if (objData.HasMultipleReleases)
                        {
                            args.Add($"{objData.GameCategory}Release release");
                        }
                    }
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine($"return Implicits.Get({relString}).BaseMasters;");
                    }
                    fg.AppendLine();

                    using (var args = new FunctionWrapper(fg,
                                                          $"public static IReadOnlyCollection<ModKey> {proto.Protocol.Namespace}"))
                    {
                        args.Add($"this ImplicitListings _");
                        if (objData.HasMultipleReleases)
                        {
                            args.Add($"{objData.GameCategory}Release release");
                        }
                    }
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine($"return Implicits.Get({relString}).Listings;");
                    }
                    fg.AppendLine();

                    using (var args = new FunctionWrapper(fg,
                                                          $"public static IReadOnlyCollection<FormKey> {proto.Protocol.Namespace}"))
                    {
                        args.Add($"this ImplicitRecordFormKeys _");
                        if (objData.HasMultipleReleases)
                        {
                            args.Add($"{objData.GameCategory}Release release");
                        }
                    }
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine($"return Implicits.Get({relString}).RecordFormKeys;");
                    }
                }
            }

            var path = Path.Combine(proto.DefFileLocation.FullName, $"../ImplicitsMixIn{Loqui.Generation.Constants.AutogeneratedMarkerString}.cs");

            fg.Generate(path);
            proto.GeneratedFiles.Add(path, ProjItemType.Compile);
        }
Ejemplo n.º 10
0
        public override async Task FinalizeGeneration(ProtocolGeneration proto)
        {
            if (proto.Protocol.Namespace.Equals("All") ||
                proto.Protocol.Namespace.Equals("Bethesda"))
            {
                return;
            }
            FileGeneration fg = new FileGeneration();

            fg.AppendLine("using System.Collections.Generic;");
            fg.AppendLine("using Mutagen.Bethesda.Plugins.Order;");
            fg.AppendLine("using Mutagen.Bethesda.Cache.Implementations;");

            fg.AppendLine();
            using (var n = new NamespaceWrapper(fg, proto.DefaultNamespace))
            {
                var setterName = $"I{proto.Protocol.Namespace}Mod";
                var getterName = $"I{proto.Protocol.Namespace}ModGetter";
                var generic    = $"<{setterName}, {getterName}>";
                using (var c = new ClassWrapper(fg, "LinkCacheMixIns"))
                {
                    c.Static = true;
                }
                using (new BraceWrapper(fg))
                {
                    using (var comment = new CommentWrapper(fg))
                    {
                        comment.Summary.AppendLine($"Creates a Link Cache using a single mod as its link target. <br/>");
                        comment.Summary.AppendLine($"Modification of the target Mod is not safe.  Internal caches can become incorrect if ");
                        comment.Summary.AppendLine($"modifications occur on content already cached.");
                        comment.Parameters.GetOrAdd("mod").AppendLine("Mod to construct the package relative to");
                        comment.Return.AppendLine($"LinkPackage attached to given mod");
                    }
                    using (var args = new FunctionWrapper(fg,
                                                          $"public static ImmutableModLinkCache{generic} ToImmutableLinkCache"))
                    {
                        args.Add($"this {getterName} mod");
                    }
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine($"return mod.ToImmutableLinkCache{generic}();");
                    }
                    fg.AppendLine();

                    using (var comment = new CommentWrapper(fg))
                    {
                        comment.Summary.AppendLine($"Creates a Link Cache using a single mod as its link target.  Mod is allowed to be modified afterwards, but");
                        comment.Summary.AppendLine($"this comes at a performance cost of not allowing much caching to be done.  If the mod is not expected to");
                        comment.Summary.AppendLine($"be modified afterwards, use ImmutableModLinkCache instead.<br/>");
                        comment.Parameters.GetOrAdd("mod").AppendLine("Mod to construct the package relative to");
                        comment.Return.AppendLine($"LinkPackage attached to given mod");
                    }
                    using (var args = new FunctionWrapper(fg,
                                                          $"public static MutableModLinkCache{generic} ToMutableLinkCache"))
                    {
                        args.Add($"this {getterName} mod");
                    }
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine($"return mod.ToMutableLinkCache{generic}();");
                    }
                    fg.AppendLine();

                    using (var comment = new CommentWrapper(fg))
                    {
                        comment.Summary.AppendLine($"Creates a new linking package relative to a load order.<br/>");
                        comment.Summary.AppendLine($"Will resolve links to the highest overriding mod containing the record being sought. <br/>");
                        comment.Summary.AppendLine($"Modification of the target LoadOrder, or Mods on the LoadOrder is not safe.  Internal caches can become");
                        comment.Summary.AppendLine($"incorrect if modifications occur on content already cached.");
                        comment.Parameters.GetOrAdd("loadOrder").AppendLine("LoadOrder to construct the package relative to");
                        comment.Return.AppendLine($"LinkPackage attached to given LoadOrder");
                    }
                    using (var args = new FunctionWrapper(fg,
                                                          $"public static ImmutableLoadOrderLinkCache{generic} ToImmutableLinkCache"))
                    {
                        args.Add($"this ILoadOrderGetter<{getterName}> loadOrder");
                    }
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine($"return loadOrder.ToImmutableLinkCache{generic}();");
                    }
                    fg.AppendLine();

                    using (var comment = new CommentWrapper(fg))
                    {
                        comment.Summary.AppendLine($"Creates a new linking package relative to a load order.<br/>");
                        comment.Summary.AppendLine($"Will resolve links to the highest overriding mod containing the record being sought. <br/>");
                        comment.Summary.AppendLine($"Modification of the target LoadOrder, or Mods on the LoadOrder is not safe.  Internal caches can become");
                        comment.Summary.AppendLine($"incorrect if modifications occur on content already cached.");
                        comment.Parameters.GetOrAdd("loadOrder").AppendLine("LoadOrder to construct the package relative to");
                        comment.Return.AppendLine($"LinkPackage attached to given LoadOrder");
                    }
                    using (var args = new FunctionWrapper(fg,
                                                          $"public static ImmutableLoadOrderLinkCache{generic} ToImmutableLinkCache"))
                    {
                        args.Add($"this ILoadOrderGetter<IModListingGetter<{getterName}>> loadOrder");
                    }
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine($"return loadOrder.ToImmutableLinkCache{generic}();");
                    }
                    fg.AppendLine();

                    using (var comment = new CommentWrapper(fg))
                    {
                        comment.Summary.AppendLine($"Creates a new linking package relative to a load order.<br/>");
                        comment.Summary.AppendLine($"Will resolve links to the highest overriding mod containing the record being sought. <br/>");
                        comment.Summary.AppendLine($"Modification of the target LoadOrder, or Mods on the LoadOrder is not safe.  Internal caches can become");
                        comment.Summary.AppendLine($"incorrect if modifications occur on content already cached.");
                        comment.Parameters.GetOrAdd("loadOrder").AppendLine("LoadOrder to construct the package relative to");
                        comment.Return.AppendLine($"LinkPackage attached to given LoadOrder");
                    }
                    using (var args = new FunctionWrapper(fg,
                                                          $"public static ImmutableLoadOrderLinkCache{generic} ToImmutableLinkCache"))
                    {
                        args.Add($"this IEnumerable<IModListingGetter<{getterName}>> loadOrder");
                    }
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine($"return loadOrder.ToImmutableLinkCache{generic}();");
                    }
                    fg.AppendLine();

                    using (var comment = new CommentWrapper(fg))
                    {
                        comment.Summary.AppendLine($"Creates a new linking package relative to a load order.<br/>");
                        comment.Summary.AppendLine($"Will resolve links to the highest overriding mod containing the record being sought. <br/>");
                        comment.Summary.AppendLine($"Modification of the target LoadOrder, or Mods on the LoadOrder is not safe.  Internal caches can become");
                        comment.Summary.AppendLine($"incorrect if modifications occur on content already cached.");
                        comment.Parameters.GetOrAdd("loadOrder").AppendLine("LoadOrder to construct the package relative to");
                        comment.Return.AppendLine($"LinkPackage attached to given LoadOrder");
                    }
                    using (var args = new FunctionWrapper(fg,
                                                          $"public static ImmutableLoadOrderLinkCache{generic} ToImmutableLinkCache"))
                    {
                        args.Add($"this IEnumerable<{getterName}> loadOrder");
                    }
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine($"return loadOrder.ToImmutableLinkCache{generic}();");
                    }
                    fg.AppendLine();

                    using (var comment = new CommentWrapper(fg))
                    {
                        comment.Summary.AppendLine($"Creates a mutable load order link cache by combining an existing immutable load order cache,");
                        comment.Summary.AppendLine($"plus a set of mods to be put at the end of the load order and allow to be mutable.");
                        comment.Parameters.GetOrAdd("immutableBaseCache").AppendLine("LoadOrderCache to use as the immutable base");
                        comment.Parameters.GetOrAdd("mutableMods").AppendLine("Set of mods to place at the end of the load order, which are allowed to be modified afterwards");
                        comment.Return.AppendLine($"LinkPackage attached to given LoadOrder");
                    }
                    using (var args = new FunctionWrapper(fg,
                                                          $"public static MutableLoadOrderLinkCache{generic} ToMutableLinkCache"))
                    {
                        args.Add($"this ILoadOrderGetter<{getterName}> immutableBaseCache");
                        args.Add($"params {setterName}[] mutableMods");
                    }
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine($"return immutableBaseCache.ToMutableLinkCache{generic}(mutableMods);");
                    }
                    fg.AppendLine();

                    using (var comment = new CommentWrapper(fg))
                    {
                        comment.Summary.AppendLine($"Creates a mutable load order link cache by combining an existing immutable load order cache,");
                        comment.Summary.AppendLine($"plus a set of mods to be put at the end of the load order and allow to be mutable.");
                        comment.Parameters.GetOrAdd("immutableBaseCache").AppendLine("LoadOrderCache to use as the immutable base");
                        comment.Parameters.GetOrAdd("mutableMods").AppendLine("Set of mods to place at the end of the load order, which are allowed to be modified afterwards");
                        comment.Return.AppendLine($"LinkPackage attached to given LoadOrder");
                    }
                    using (var args = new FunctionWrapper(fg,
                                                          $"public static MutableLoadOrderLinkCache{generic} ToMutableLinkCache"))
                    {
                        args.Add($"this ILoadOrderGetter<IModListingGetter<{getterName}>> immutableBaseCache");
                        args.Add($"params {setterName}[] mutableMods");
                    }
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine($"return immutableBaseCache.ToMutableLinkCache{generic}(mutableMods);");
                    }
                    fg.AppendLine();

                    using (var comment = new CommentWrapper(fg))
                    {
                        comment.Summary.AppendLine($"Creates a mutable load order link cache by combining an existing immutable load order cache,");
                        comment.Summary.AppendLine($"plus a set of mods to be put at the end of the load order and allow to be mutable.");
                        comment.Parameters.GetOrAdd("immutableBaseCache").AppendLine("LoadOrderCache to use as the immutable base");
                        comment.Parameters.GetOrAdd("mutableMods").AppendLine("Set of mods to place at the end of the load order, which are allowed to be modified afterwards");
                        comment.Return.AppendLine($"LinkPackage attached to given LoadOrder");
                    }
                    using (var args = new FunctionWrapper(fg,
                                                          $"public static MutableLoadOrderLinkCache{generic} ToMutableLinkCache"))
                    {
                        args.Add($"this IEnumerable<{getterName}> immutableBaseCache");
                        args.Add($"params {setterName}[] mutableMods");
                    }
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine($"return immutableBaseCache.ToMutableLinkCache{generic}(mutableMods);");
                    }
                    fg.AppendLine();
                }
            }

            var path = Path.Combine(proto.DefFileLocation.FullName, $"LinkCacheMixIns{Loqui.Generation.Constants.AutogeneratedMarkerString}.cs");

            fg.Generate(path);
            proto.GeneratedFiles.Add(path, ProjItemType.Compile);
        }
Ejemplo n.º 11
0
 public bool TryGetProtocol(ProtocolKey protocol, out ProtocolGeneration protoGen)
 {
     return(_protocols.TryGetValue(protocol, out protoGen));
 }
Ejemplo n.º 12
0
 public ProtocolGeneration AddProtocol(ProtocolGeneration protoGen)
 {
     _protocols[protoGen.Protocol] = protoGen;
     return(protoGen);
 }
Ejemplo n.º 13
0
        public override async Task FinalizeGeneration(ProtocolGeneration proto)
        {
            FileGeneration fg = new FileGeneration();

            if (LinkInterfaceModule.ObjectMappings.TryGetValue(proto.Protocol, out var linkInterfaces))
            {
                Dictionary <string, List <string> > reverse = new Dictionary <string, List <string> >();

                fg.AppendLine("# Link Interfaces");
                fg.AppendLine("Link Interfaces are used by FormLinks to point to several record types at once.  For example, a Container record might be able to contain Armors, Weapons, Ingredients, etc.");
                fg.AppendLine();
                fg.AppendLine("An interface would be defined such as 'IItem', which all Armor, Weapon, Ingredients would all implement.");
                fg.AppendLine();
                fg.AppendLine("A `FormLink<IItem>` could then point to all those record types by pointing to the interface instead.");
                fg.AppendLine($"## Interfaces to Concrete Classes");
                foreach (var interf in linkInterfaces.OrderBy(x => x.Key))
                {
                    fg.AppendLine($"### {interf.Key}");
                    foreach (var obj in interf.Value.OrderBy(o => o.Name))
                    {
                        fg.AppendLine($"- {obj.Name}");
                        reverse.GetOrAdd(obj.Name).Add(interf.Key);
                    }
                }

                fg.AppendLine($"## Concrete Classes to Interfaces");
                foreach (var obj in reverse.OrderBy(x => x.Key))
                {
                    fg.AppendLine($"### {obj.Key}");
                    foreach (var interf in obj.Value.OrderBy(x => x))
                    {
                        fg.AppendLine($"- {interf}");
                    }
                }
            }

            var path = Path.Combine(proto.DefFileLocation.FullName, $"../Documentation/LinkInterfaceDocumentation{Loqui.Generation.Constants.AutogeneratedMarkerString}.md");

            if (fg.Count > 0)
            {
                fg.Generate(path);
            }


            fg = new FileGeneration();

            if (AspectInterfaceModule.ObjectMappings.TryGetValue(proto.Protocol, out var aspectInterfaces))
            {
                Dictionary <string, List <string> > reverse = new Dictionary <string, List <string> >();

                fg.AppendLine("# Aspect Interfaces");
                fg.AppendLine("Aspect Interfaces expose common aspects of records.  For example, `INamed` are implemented by all records that have a `Name`.");
                fg.AppendLine();
                fg.AppendLine("Functions can then be written that take in `INamed`, allowing any record that has a name to be passed in.");
                fg.AppendLine($"## Interfaces to Concrete Classes");
                foreach (var interf in aspectInterfaces.OrderBy(x => x.Key.Name))
                {
                    fg.AppendLine($"### {interf.Key.Name}");
                    foreach (var obj in interf.Value.OrderBy(x => x.Name))
                    {
                        fg.AppendLine($"- {obj.Name}");
                        reverse.GetOrAdd(obj.Name).Add(interf.Key.Name);
                    }
                }

                fg.AppendLine($"## Concrete Classes to Interfaces");
                foreach (var obj in reverse.OrderBy(x => x.Key))
                {
                    fg.AppendLine($"### {obj.Key}");
                    foreach (var interf in obj.Value.OrderBy(x => x))
                    {
                        fg.AppendLine($"- {interf}");
                    }
                }
            }

            path = Path.Combine(proto.DefFileLocation.FullName, $"../Documentation/AspectInterfaceDocumentation{Loqui.Generation.Constants.AutogeneratedMarkerString}.md");
            if (fg.Count > 0)
            {
                fg.Generate(path);
            }
        }
Ejemplo n.º 14
0
 public override async Task FinalizeGeneration(ProtocolGeneration proto)
 {
     GenerateCommonXSDForProto(proto);
     await base.FinalizeGeneration(proto);
 }
Ejemplo n.º 15
0
 public FilePath CommonXSDLocation(ProtocolGeneration proto) => new FilePath(Path.Combine(proto.GenerationFolder.FullName, "Common.xsd"));