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); }
public Task PrepareGeneration(ProtocolGeneration proto) { return(Task.WhenAll( subModules.Select( (subGen) => { return subGen.PrepareGeneration(proto); }))); }
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);");
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); }
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); }
public ClassGeneration(LoquiGenerator gen, ProtocolGeneration protoGen, FilePath sourceFile) : base(gen, protoGen, sourceFile) { }
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); }
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); }
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); }
public bool TryGetProtocol(ProtocolKey protocol, out ProtocolGeneration protoGen) { return(_protocols.TryGetValue(protocol, out protoGen)); }
public ProtocolGeneration AddProtocol(ProtocolGeneration protoGen) { _protocols[protoGen.Protocol] = protoGen; return(protoGen); }
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); } }
public override async Task FinalizeGeneration(ProtocolGeneration proto) { GenerateCommonXSDForProto(proto); await base.FinalizeGeneration(proto); }
public FilePath CommonXSDLocation(ProtocolGeneration proto) => new FilePath(Path.Combine(proto.GenerationFolder.FullName, "Common.xsd"));