Ejemplo n.º 1
0
        private async Task GenerateForRecord(ObjectGeneration obj, FileGeneration fg)
        {
            if (!obj.IsTopClass)
            {
                return;
            }

            using (var args = new FunctionWrapper(fg,
                                                  $"public{obj.FunctionOverride()}async Task WriteToXmlFolder"))
            {
                args.Add("DirectoryPath dir");
                args.Add("string name");
                args.Add("XElement node");
                args.Add("int counter");
                args.Add($"ErrorMaskBuilder? errorMask");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new ArgsWrapper(fg,
                                                  "this.WriteToXml"))
                {
                    args.Add("node: node");
                    args.Add("errorMask: errorMask");
                    args.Add("translationMask: null");
                }
            }
        }
Ejemplo n.º 2
0
        private void GenerateCustomBinaryEndCreatePartial(ObjectGeneration obj, FileGeneration fg)
        {
            var data = obj.GetObjectData();

            if (data.CustomBinaryEnd == CustomEnd.Off)
            {
                return;
            }
            if (data.CustomBinaryEnd == CustomEnd.Normal)
            {
                using (var args = new ArgsWrapper(fg,
                                                  $"public static partial void CustomBinaryEndImport"))
                {
                    args.Add($"{ReaderClass} {ReaderMemberName}");
                    args.Add($"{obj.Interface(getter: false, internalInterface: true)} obj");
                }
                using (var args = new FunctionWrapper(fg,
                                                      $"public static void CustomBinaryEndImportPublic"))
                {
                    args.Add($"{ReaderClass} {ReaderMemberName}");
                    args.Add($"{obj.Interface(getter: false, internalInterface: true)} obj");
                }
                using (new BraceWrapper(fg))
                {
                    using (var args = new ArgsWrapper(fg,
                                                      $"CustomBinaryEndImport"))
                    {
                        args.AddPassArg(ReaderMemberName);
                        args.AddPassArg($"obj");
                    }
                }
            }
        }
Ejemplo n.º 3
0
 public override async Task GenerateInCommonMixin(ObjectGeneration obj, FileGeneration fg)
 {
     if (!await obj.IsMajorRecord())
     {
         return;
     }
     if (!obj.IsTopClass)
     {
         return;
     }
     using (var args = new FunctionWrapper(fg,
                                           $"public static {nameof(IMajorRecordCommon)} {nameof(IDuplicatable.Duplicate)}"))
     {
         //ToDo
         // Modify to getter interface after copy is refactored
         args.Add($"this {obj.ObjectName} item");
         args.Add("Func<FormKey> getNextFormKey");
         args.Add($"IList<({nameof(IMajorRecordCommon)} Record, FormKey OriginalFormKey)>? duplicatedRecords = null");
     }
     using (new BraceWrapper(fg))
     {
         using (var args = new ArgsWrapper(fg,
                                           $"return {obj.CommonClassInstance("item", LoquiInterfaceType.IGetter, CommonGenerics.Class, MaskType.Normal)}.{nameof(IDuplicatable.Duplicate)}"))
         {
             args.AddPassArg("item");
             args.AddPassArg("getNextFormKey");
             args.AddPassArg("duplicatedRecords");
         }
     }
 }
Ejemplo n.º 4
0
        public override async Task GenerateInCommonMixin(ObjectGeneration obj, FileGeneration fg)
        {
            await base.GenerateInCommonMixin(obj, fg);

            if (!await obj.IsMajorRecord())
            {
                return;
            }
            using (var args = new FunctionWrapper(fg,
                                                  $"public static {obj.ObjectName} Duplicate{obj.GetGenericTypes(MaskType.Normal, MaskType.NormalGetter)}"))
            {
                args.Wheres.AddRange(obj.GenericTypeMaskWheres(LoquiInterfaceType.IGetter, MaskType.Normal, MaskType.NormalGetter));
                args.Add($"this {obj.Interface(obj.GetGenericTypes(MaskType.NormalGetter), getter: true, internalInterface: true)} item");
                args.Add($"{nameof(FormKey)} formKey");
                args.Add($"{obj.Mask(MaskType.Translation)}? copyMask = null");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new ArgsWrapper(fg,
                                                  $"return {obj.CommonClassInstance("item", LoquiInterfaceType.IGetter, CommonGenerics.Functions, MaskType.NormalGetter)}.Duplicate{obj.GetGenericTypes(MaskType.Normal, MaskType.NormalGetter, MaskType.Translation)}"))
                {
                    args.AddPassArg("item");
                    args.AddPassArg("formKey");
                    args.Add("copyMask: copyMask?.GetCrystal()");
                }
            }
            fg.AppendLine();
        }
 public static void GenerateWritePartialMethods(
     FileGeneration fg,
     ObjectGeneration obj,
     TypeGeneration field,
     bool isAsync)
 {
     using (var args = new FunctionWrapper(fg,
                                           $"public static partial void WriteBinary{field.Name}Custom{obj.GetGenericTypes(MaskType.Normal)}"))
     {
         args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.IGetter, defs: obj.Generics));
         args.SemiColon = true;
         args.Add($"{nameof(MutagenWriter)} writer");
         args.Add($"{obj.Interface(getter: true, internalInterface: true)} item");
     }
     fg.AppendLine();
     using (var args = new FunctionWrapper(fg,
                                           $"public static void WriteBinary{field.Name}{obj.GetGenericTypes(MaskType.Normal)}"))
     {
         args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.IGetter, defs: obj.Generics));
         args.Add($"{nameof(MutagenWriter)} writer");
         args.Add($"{obj.Interface(getter: true, internalInterface: true)} item");
     }
     using (new BraceWrapper(fg))
     {
         using (var args = new ArgsWrapper(fg,
                                           $"WriteBinary{field.Name}Custom"))
         {
             args.Add("writer: writer");
             args.Add("item: item");
         }
     }
     fg.AppendLine();
 }
Ejemplo n.º 6
0
        public static void GenerateCreatePartialMethods(
            FileGeneration fg,
            ObjectGeneration obj,
            TypeGeneration field,
            bool isAsync,
            bool useReturnValue)
        {
            var fieldData            = field.GetFieldData();
            var returningParseResult = useReturnValue && fieldData.HasTrigger;

            if (!isAsync)
            {
                using (var args = new FunctionWrapper(fg,
                                                      $"public static partial {(returningParseResult ? nameof(ParseResult) : "void")} FillBinary{field.Name}Custom")
                {
                    SemiColon = true
                })
                {
                    args.Add($"{nameof(MutagenFrame)} frame");
                    args.Add($"{obj.Interface(getter: false, internalInterface: true)} item");
                    if (returningParseResult && obj.GetObjectType() == ObjectType.Subrecord)
                    {
                        args.Add($"{nameof(PreviousParse)} lastParsed");
                    }
                }
                fg.AppendLine();
            }
        }
Ejemplo n.º 7
0
 private void GenerateGetGroup(ObjectGeneration obj, FileGeneration fg)
 {
     using (var args = new FunctionWrapper(fg,
                                           "public object GetGroup"))
     {
         args.Add($"{obj.Interface(getter: true)} obj");
         args.Add("Type type");
     }
     using (new BraceWrapper(fg))
     {
         fg.AppendLine("switch (type.Name)");
         using (new BraceWrapper(fg))
         {
             foreach (var field in obj.IterateFields())
             {
                 if (!(field is LoquiType loqui))
                 {
                     continue;
                 }
                 if (loqui.TargetObjectGeneration?.GetObjectData().ObjectType != ObjectType.Group)
                 {
                     continue;
                 }
                 if (!loqui.TryGetSpecificationAsObject("T", out var subObj))
                 {
                     throw new ArgumentException();
                 }
                 fg.AppendLine($"case \"{subObj.Name}\":");
                 fg.AppendLine($"case \"{subObj.Interface(getter: true)}\":");
                 fg.AppendLine($"case \"{subObj.Interface(getter: false)}\":");
                 if (subObj.HasInternalGetInterface)
                 {
                     fg.AppendLine($"case \"{subObj.Interface(getter: true, internalInterface: true)}\":");
                 }
                 if (subObj.HasInternalSetInterface)
                 {
                     fg.AppendLine($"case \"{subObj.Interface(getter: false, internalInterface: true)}\":");
                 }
                 using (new DepthWrapper(fg))
                 {
                     if (loqui.TargetObjectGeneration.Name.EndsWith("ListGroup"))
                     {
                         fg.AppendLine($"return obj.{field.Name}.Records;");
                     }
                     else
                     {
                         fg.AppendLine($"return obj.{field.Name};");
                     }
                 }
             }
             fg.AppendLine("default:");
             using (new DepthWrapper(fg))
             {
                 fg.AppendLine("throw new ArgumentException($\"Unknown major record type: {type}\");");
             }
         }
     }
     fg.AppendLine();
 }
Ejemplo n.º 8
0
        public override async Task GenerateInClass(ObjectGeneration obj, FileGeneration fg)
        {
            await base.GenerateInClass(obj, fg);

            if (WantsTryCreateFromBinary(obj))
            {
                using (var args = new FunctionWrapper(fg,
                                                      "public static bool TryCreateFromBinary"))
                {
                    foreach (var(API, Public) in this.MainAPI.ReaderAPI.IterateAPI(
                                 obj,
                                 TranslationDirection.Reader,
                                 new APILine(OutItemKey, $"out {obj.ObjectName} item")))
                    {
                        if (Public)
                        {
                            args.Add(API.Result);
                        }
                    }
                }
                using (new BraceWrapper(fg))
                {
                    fg.AppendLine($"var startPos = {ReaderMemberName}.Position;");
                    using (var args = new ArgsWrapper(fg,
                                                      $"item = CreateFromBinary"))
                    {
                        args.Add(this.MainAPI.PassArgs(obj, TranslationDirection.Reader));
                    }
                    fg.AppendLine($"return startPos != {ReaderMemberName}.Position;");
                }
            }
            await GenerateBinaryOverlayCreates(obj, fg);
        }
Ejemplo n.º 9
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);");
 public static void GenerateCreatePartialMethods(
     FileGeneration fg,
     ObjectGeneration obj,
     TypeGeneration field,
     bool isAsync)
 {
     if (!isAsync)
     {
         using (var args = new FunctionWrapper(fg,
                                               $"public static partial void FillBinary{field.Name}Custom")
         {
             SemiColon = true
         })
         {
             args.Add($"{nameof(MutagenFrame)} frame");
             args.Add($"{obj.Interface(getter: false, internalInterface: true)} item");
         }
         fg.AppendLine();
     }
 }
Ejemplo n.º 11
0
 public static void GenerateConverterMember(FileGeneration fg, ObjectGeneration objGen, RecordTypeConverter recordTypeConverter, string nickName)
 {
     if (recordTypeConverter == null || recordTypeConverter.FromConversions.Count == 0)
     {
         return;
     }
     using (var args = new ArgsWrapper(fg,
                                       $"public static RecordTypeConverter {nickName}Converter = new RecordTypeConverter"))
     {
         foreach (var conv in recordTypeConverter.FromConversions)
         {
             args.Add((gen) =>
             {
                 using (var args2 = new FunctionWrapper(gen,
                                                        "new KeyValuePair<RecordType, RecordType>"))
                 {
                     args2.Add($"new RecordType(\"{conv.Key.Type}\")");
                     args2.Add($"new RecordType(\"{conv.Value.Type}\")");
                 }
             });
         }
     }
 }
Ejemplo n.º 12
0
        public override void GenerateCopyIn(
            FileGeneration fg,
            ObjectGeneration objGen,
            TypeGeneration typeGen,
            Accessor frameAccessor,
            Accessor itemAccessor,
            Accessor errorMaskAccessor,
            Accessor translationMaskAccessor)
        {
            FormLinkType linkType = typeGen as FormLinkType;

            MaskGenerationUtility.WrapErrorFieldIndexPush(fg,
                                                          () =>
            {
                if (itemAccessor.IsAssignment)
                {
                    using (var args = new ArgsWrapper(fg,
                                                      $"{itemAccessor} = {(linkType.FormIDType == FormLinkType.FormIDTypeEnum.Normal ? "FormKey" : "RecordType")}XmlTranslation.Instance.Parse"))
                    {
                        args.AddPassArg("node");
                        args.AddPassArg("errorMask");
                    }
                }
                else
                {
                    using (var args = new FunctionWrapper(fg,
                                                          itemAccessor.Assign($"new {linkType.DirectTypeName(getter: false)}")))
                    {
                        args.Add(subFg =>
                        {
                            using (var subArgs = new FunctionWrapper(subFg,
                                                                     $"FormKeyXmlTranslation.Instance.Parse"))
                            {
                                subArgs.AddPassArg("node");
                                subArgs.AddPassArg("errorMask");
                            }
                        });
                    }
                }
            },
                                                          indexAccessor: typeGen.HasIndex?typeGen.IndexEnumInt: null,
                                                          errorMaskAccessor: errorMaskAccessor,
                                                          doIt: typeGen.HasIndex);
        }
Ejemplo n.º 13
0
        public override async Task GenerateInClass(ObjectGeneration obj, FileGeneration fg)
        {
            if (obj.GetObjectData().ObjectType != ObjectType.Mod)
            {
                return;
            }
            var objData = obj.GetObjectData();

            // Game release member
            if (objData.GameReleaseOptions != null)
            {
                fg.AppendLine($"public {ReleaseEnumName(obj)} {ReleaseEnumName(obj)} {{ get; }}");
                fg.AppendLine($"public override {nameof(GameRelease)} GameRelease => {ReleaseEnumName(obj)}.ToGameRelease();");
            }
            else
            {
                fg.AppendLine($"public override {nameof(GameRelease)} GameRelease => {nameof(GameRelease)}.{obj.GetObjectData().GameCategory};");
            }

            // Interfaces
            fg.AppendLine($"IReadOnlyCache<T, {nameof(FormKey)}> {nameof(IModGetter)}.{nameof(IModGetter.GetTopLevelGroupGetter)}<T>() => this.{nameof(IModGetter.GetTopLevelGroupGetter)}<T>();");
            fg.AppendLine($"ICache<T, {nameof(FormKey)}> {nameof(IMod)}.{nameof(IMod.GetGroup)}<T>() => this.GetGroup<T>();");
            fg.AppendLine($"void IModGetter.WriteToBinary(string path, {nameof(BinaryWriteParameters)}? param) => this.WriteToBinary(path, importMask: null, param: param);");
            fg.AppendLine($"void IModGetter.WriteToBinaryParallel(string path, {nameof(BinaryWriteParameters)}? param) => this.WriteToBinaryParallel(path, param);");
            fg.AppendLine($"IMask<bool> {nameof(IEqualsMask)}.{nameof(IEqualsMask.GetEqualsMask)}(object rhs, EqualsMaskHelper.Include include = EqualsMaskHelper.Include.OnlyFailures) => {obj.MixInClassName}.GetEqualsMask(this, ({obj.Interface(getter: true, internalInterface: true)})rhs, include);");

            // Localization enabled member
            if (obj.GetObjectData().UsesStringFiles)
            {
                fg.AppendLine($"public override bool CanUseLocalization => true;");
                fg.AppendLine($"public override bool UsingLocalization");
                using (new BraceWrapper(fg))
                {
                    fg.AppendLine($"get => this.ModHeader.Flags.HasFlag({obj.GetObjectData().GameCategory}ModHeader.HeaderFlag.Localized);");
                    fg.AppendLine($"set => this.ModHeader.Flags.SetFlag({obj.GetObjectData().GameCategory}ModHeader.HeaderFlag.Localized, value);");
                }
            }
            else
            {
                fg.AppendLine($"public override bool CanUseLocalization => false;");
                fg.AppendLine($"public override bool UsingLocalization");
                using (new BraceWrapper(fg))
                {
                    fg.AppendLine("get => false;");
                    fg.AppendLine("set => throw new ArgumentException(\"Tried to set localization flag on unsupported mod type\");");
                }
            }

            // Master references member
            fg.AppendLine($"[DebuggerBrowsable(DebuggerBrowsableState.Never)]");
            fg.AppendLine($"IList<MasterReference> IMod.MasterReferences => this.ModHeader.MasterReferences;");
            fg.AppendLine($"[DebuggerBrowsable(DebuggerBrowsableState.Never)]");
            fg.AppendLine($"IReadOnlyList<IMasterReferenceGetter> IModGetter.MasterReferences => this.ModHeader.MasterReferences;");

            // NextObjectID member
            fg.AppendLine($"[DebuggerBrowsable(DebuggerBrowsableState.Never)]");
            fg.AppendLine($"uint IMod.NextFormID");
            using (new BraceWrapper(fg))
            {
                fg.AppendLine($"get => this.ModHeader.Stats.NextFormID;");
                fg.AppendLine($"set => this.ModHeader.Stats.NextFormID = value;");
            }
            fg.AppendLine($"[DebuggerBrowsable(DebuggerBrowsableState.Never)]");
            fg.AppendLine($"uint IModGetter.NextFormID => this.ModHeader.Stats.NextFormID;");

            using (var args = new FunctionWrapper(fg,
                                                  $"public {obj.Name}"))
            {
                args.Add($"{nameof(ModKey)} modKey");
                if (objData.GameReleaseOptions != null)
                {
                    args.Add($"{ReleaseEnumName(obj)} release");
                }
            }
            using (new DepthWrapper(fg))
            {
                fg.AppendLine(": base(modKey)");
            }
            using (new BraceWrapper(fg))
            {
                fg.AppendLine("this.ModHeader.Stats.NextFormID = GetDefaultInitialNextFormID();");
                if (objData.GameReleaseOptions != null)
                {
                    fg.AppendLine($"this.{ReleaseEnumName(obj)} = release;");
                }
                await obj.GenerateInitializer(fg);

                fg.AppendLine($"CustomCtor();");
            }

            using (var args = new FunctionWrapper(fg,
                                                  "public void AddRecords"))
            {
                args.Add($"{obj.Name} rhsMod");
                args.Add($"GroupMask? mask = null");
            }
            using (new BraceWrapper(fg))
            {
                foreach (var field in obj.IterateFields())
                {
                    if (!(field is LoquiType loqui))
                    {
                        continue;
                    }
                    if (loqui.TargetObjectGeneration.GetObjectType() != ObjectType.Group)
                    {
                        continue;
                    }
                    fg.AppendLine($"if (mask?.{field.Name} ?? true)");
                    using (new BraceWrapper(fg))
                    {
                        if (loqui.TargetObjectGeneration.Name == "Group")
                        {
                            fg.AppendLine($"this.{field.Name}.RecordCache.Set(rhsMod.{field.Name}.RecordCache.Items);");
                        }
                        else
                        {
                            fg.AppendLine($"if (rhsMod.{field.Name}.Records.Count > 0)");
                            using (new BraceWrapper(fg))
                            {
                                fg.AppendLine("throw new NotImplementedException(\"Cell additions need implementing\");");
                            }
                        }
                    }
                }
            }
            fg.AppendLine();

            using (var args = new FunctionWrapper(fg,
                                                  $"public Dictionary<FormKey, {nameof(IMajorRecordCommon)}> CopyInDuplicate"))
            {
                args.Add($"{obj.Name} rhs");
                args.Add($"GroupMask? mask = null");
            }
            using (new BraceWrapper(fg))
            {
                fg.AppendLine($"var duppedRecords = new List<({nameof(IMajorRecordCommon)} Record, FormKey OriginalFormKey)>();");
                foreach (var field in obj.IterateFields())
                {
                    if (!(field is LoquiType loqui))
                    {
                        continue;
                    }
                    if (loqui.TargetObjectGeneration.GetObjectType() != ObjectType.Group)
                    {
                        continue;
                    }
                    var dictGroup = loqui.TargetObjectGeneration.Name == "Group";
                    fg.AppendLine($"if (mask?.{field.Name} ?? true)");
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine($"this.{field.Name}.{(dictGroup ? "RecordCache" : "Records")}.{(dictGroup ? "Set" : "AddRange")}(");
                        using (new DepthWrapper(fg))
                        {
                            fg.AppendLine($"rhs.{field.Name}.Records");
                            using (new DepthWrapper(fg))
                            {
                                fg.AppendLine($".Select(i => i.Duplicate(this.GetNextFormKey, duppedRecords))");
                                fg.AppendLine($".Cast<{loqui.GetGroupTarget().Name}>());");
                            }
                        }
                    }
                }
                fg.AppendLine($"var router = new Dictionary<FormKey, {nameof(IMajorRecordCommon)}>();");
                fg.AppendLine($"router.Set(duppedRecords.Select(dup => new KeyValuePair<FormKey, {nameof(IMajorRecordCommon)}>(dup.OriginalFormKey, dup.Record)));");
                fg.AppendLine($"var mapping = new Dictionary<FormKey, FormKey>();");
                fg.AppendLine($"var package = this.{nameof(ILinkCacheExt.ToImmutableLinkCache)}();");
                fg.AppendLine("foreach (var rec in router.Values)");
                using (new BraceWrapper(fg))
                {
                    fg.AppendLine($"rec.RemapLinks(mapping);");
                }
                fg.AppendLine($"return router;");
            }
            fg.AppendLine();

            using (var args = new FunctionWrapper(fg,
                                                  "public override void SyncRecordCount"))
            {
            }
            using (new BraceWrapper(fg))
            {
                fg.AppendLine("this.ModHeader.Stats.NumRecords = GetRecordCount();");
            }
            fg.AppendLine();

            using (var args = new FunctionWrapper(fg,
                                                  "public uint GetRecordCount"))
            {
            }
            using (new BraceWrapper(fg))
            {
                fg.AppendLine("uint count = (uint)this.EnumerateMajorRecords().Count();");
                foreach (var field in obj.IterateFields())
                {
                    if (!(field is LoquiType loqui))
                    {
                        continue;
                    }
                    if (loqui.TargetObjectGeneration.GetObjectType() != ObjectType.Group)
                    {
                        continue;
                    }
                    if (loqui.TargetObjectGeneration.Name == "ListGroup")
                    {
                        fg.AppendLine($"count += {field.Name}.Records.Count > 0 ? 1 : default(uint);");
                    }
                    else
                    {
                        fg.AppendLine($"count += {field.Name}.RecordCache.Count > 0 ? 1 : default(uint);");
                    }
                }
                fg.AppendLine("GetCustomRecordCount((customCount) => count += customCount);");
                fg.AppendLine("return count;");
            }
            fg.AppendLine();

            fg.AppendLine("partial void GetCustomRecordCount(Action<uint> setter);");
            fg.AppendLine();

            await base.GenerateInClass(obj, fg);
        }
Ejemplo n.º 14
0
        public override async Task GenerateInVoid(ObjectGeneration obj, FileGeneration fg)
        {
            if (obj.GetObjectType() != ObjectType.Mod)
            {
                return;
            }
            using (new NamespaceWrapper(fg, obj.Namespace))
            {
                var objData = obj.GetObjectData();
                fg.AppendLine("public class GroupMask");
                using (new BraceWrapper(fg))
                {
                    foreach (var field in obj.IterateFields())
                    {
                        if (!(field is LoquiType loqui))
                        {
                            continue;
                        }
                        if (loqui.TargetObjectGeneration == null)
                        {
                            continue;
                        }
                        if (loqui.TargetObjectGeneration.GetObjectType() != ObjectType.Group)
                        {
                            continue;
                        }
                        fg.AppendLine($"public bool {loqui.Name};");
                    }

                    fg.AppendLine("public GroupMask()");
                    using (new BraceWrapper(fg))
                    {
                    }

                    fg.AppendLine("public GroupMask(bool defaultValue)");
                    using (new BraceWrapper(fg))
                    {
                        foreach (var field in obj.IterateFields())
                        {
                            if (!(field is LoquiType loqui))
                            {
                                continue;
                            }
                            if (loqui.TargetObjectGeneration == null)
                            {
                                continue;
                            }
                            if (loqui.TargetObjectGeneration.GetObjectType() != ObjectType.Group)
                            {
                                continue;
                            }
                            fg.AppendLine($"{loqui.Name} = defaultValue;");
                        }
                    }
                }
                fg.AppendLine();

                fg.AppendLine($"public interface I{obj.Name}DisposableGetter : {obj.Interface(getter: true, internalInterface: true)}, IModDisposeGetter");
                using (new BraceWrapper(fg))
                {
                }
                fg.AppendLine();

                if (objData.GameReleaseOptions != null)
                {
                    using (var comment = new CommentWrapper(fg))
                    {
                        comment.Summary.AppendLine($"Different game release versions a {ModName(obj)} mod can have");
                    }
                    fg.AppendLine($"public enum {ReleaseEnumName(obj)}");
                    using (new BraceWrapper(fg))
                    {
                        using (var comma = new CommaWrapper(fg))
                        {
                            foreach (var opt in objData.GameReleaseOptions)
                            {
                                comma.Add($"{opt} = {(int)opt}");
                            }
                        }
                    }
                    fg.AppendLine();

                    using (var c = new ClassWrapper(fg, $"{ReleaseEnumName(obj)}Ext"))
                    {
                        c.Static = true;
                    }
                    using (new BraceWrapper(fg))
                    {
                        using (var args = new FunctionWrapper(fg,
                                                              $"public static {nameof(GameRelease)} ToGameRelease"))
                        {
                            args.Add($"this {ReleaseEnumName(obj)} release");
                        }
                        using (new BraceWrapper(fg))
                        {
                            fg.AppendLine("return release switch");
                            using (new BraceWrapper(fg)
                            {
                                AppendSemicolon = true
                            })
                            {
                                using (var comma = new CommaWrapper(fg))
                                {
                                    foreach (var item in objData.GameReleaseOptions)
                                    {
                                        comma.Add($"{ReleaseEnumName(obj)}.{item} => {nameof(GameRelease)}.{item}");
                                    }
                                    comma.Add("_ => throw new ArgumentException()");
                                }
                            }
                        }
                        fg.AppendLine();

                        using (var args = new FunctionWrapper(fg,
                                                              $"public static {ReleaseEnumName(obj)} To{ReleaseEnumName(obj)}"))
                        {
                            args.Add($"this {nameof(GameRelease)} release");
                        }
                        using (new BraceWrapper(fg))
                        {
                            fg.AppendLine("return release switch");
                            using (new BraceWrapper(fg)
                            {
                                AppendSemicolon = true
                            })
                            {
                                using (var comma = new CommaWrapper(fg))
                                {
                                    foreach (var item in objData.GameReleaseOptions)
                                    {
                                        comma.Add($"{nameof(GameRelease)}.{item} => {ReleaseEnumName(obj)}.{item}");
                                    }
                                    comma.Add("_ => throw new ArgumentException()");
                                }
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 15
0
        public override async Task GenerateInCommonMixin(ObjectGeneration obj, FileGeneration fg)
        {
            await base.GenerateInCommonMixin(obj, fg);

            if (obj.GetObjectType() != ObjectType.Mod)
            {
                return;
            }
            using (var args = new FunctionWrapper(fg,
                                                  $"public static IReadOnlyCache<T, FormKey> {nameof(IModGetter.GetTopLevelGroupGetter)}<T>"))
            {
                args.Wheres.Add($"where T : {nameof(IMajorRecordCommonGetter)}");
                args.Add($"this {obj.Interface(getter: true)} obj");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new ArgsWrapper(fg,
                                                  $"return (IReadOnlyCache<T, FormKey>){obj.CommonClassInstance("obj", LoquiInterfaceType.IGetter, CommonGenerics.Class, MaskType.Normal)}.GetGroup<T>"))
                {
                    args.AddPassArg("obj");
                }
            }
            fg.AppendLine();

            using (var args = new FunctionWrapper(fg,
                                                  "public static ICache<T, FormKey> GetGroup<T>"))
            {
                args.Wheres.Add($"where T : {nameof(IMajorRecordCommon)}");
                args.Add($"this {obj.Interface(getter: false)} obj");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new ArgsWrapper(fg,
                                                  $"return (ICache<T, FormKey>){obj.CommonClassInstance("obj", LoquiInterfaceType.IGetter, CommonGenerics.Class, MaskType.Normal)}.GetGroup<T>"))
                {
                    args.AddPassArg("obj");
                }
            }
            fg.AppendLine();

            using (var args = new FunctionWrapper(fg,
                                                  $"public static void WriteToBinaryParallel"))
            {
                args.Add($"this {obj.Interface(getter: true, internalInterface: false)} item");
                args.Add($"Stream stream");
                args.Add($"{nameof(BinaryWriteParameters)}? param = null");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new ArgsWrapper(fg,
                                                  $"{obj.CommonClass(LoquiInterfaceType.IGetter, CommonGenerics.Class, MaskType.Normal)}.WriteParallel"))
                {
                    args.AddPassArg("item");
                    args.AddPassArg("stream");
                    args.Add($"param: param ?? {nameof(BinaryWriteParameters)}.{nameof(BinaryWriteParameters.Default)}");
                    args.Add("modKey: item.ModKey");
                }
            }
            fg.AppendLine();

            using (var args = new FunctionWrapper(fg,
                                                  $"public static void WriteToBinaryParallel"))
            {
                args.Add($"this {obj.Interface(getter: true, internalInterface: false)} item");
                args.Add($"string path");
                args.Add($"{nameof(BinaryWriteParameters)}? param = null");
            }
            using (new BraceWrapper(fg))
            {
                fg.AppendLine($"param ??= {nameof(BinaryWriteParameters)}.{nameof(BinaryWriteParameters.Default)};");
                using (var args = new ArgsWrapper(fg,
                                                  $"var modKey = param.{nameof(BinaryWriteParameters.RunMasterMatch)}"))
                {
                    args.Add("mod: item");
                    args.AddPassArg("path");
                }
                if (obj.GetObjectData().UsesStringFiles)
                {
                    fg.AppendLine("bool disposeStrings = param.StringsWriter == null;");
                    fg.AppendLine("param.StringsWriter ??= EnumExt.HasFlag((int)item.ModHeader.Flags, (int)ModHeaderCommonFlag.Localized) ? new StringsWriter(modKey, Path.Combine(Path.GetDirectoryName(path)!, \"Strings\")) : null;");
                }
                fg.AppendLine("using (var stream = new FileStream(path, FileMode.Create, FileAccess.Write))");
                using (new BraceWrapper(fg))
                {
                    using (var args = new ArgsWrapper(fg,
                                                      $"{obj.CommonClass(LoquiInterfaceType.IGetter, CommonGenerics.Class, MaskType.Normal)}.WriteParallel"))
                    {
                        args.AddPassArg("item");
                        args.AddPassArg("stream");
                        args.Add($"param: param");
                        args.AddPassArg("modKey");
                    }
                }
                if (obj.GetObjectData().UsesStringFiles)
                {
                    fg.AppendLine("if (disposeStrings)");
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine("param.StringsWriter?.Dispose();");
                    }
                }
            }
            fg.AppendLine();
        }
Ejemplo n.º 16
0
        public override async Task GenerateInCommon(ObjectGeneration obj, FileGeneration fg, MaskTypeSet maskTypes)
        {
            bool getter = maskTypes.Applicable(LoquiInterfaceType.IGetter, CommonGenerics.Class);
            bool setter = maskTypes.Applicable(LoquiInterfaceType.ISetter, CommonGenerics.Class);

            if (!getter && !setter)
            {
                return;
            }
            var accessor = new Accessor("obj");

            if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No)
            {
                return;
            }
            var overrideStr = await obj.FunctionOverride(async c => await MajorRecordModule.HasMajorRecords(c, includeBaseClass : false, includeSelf : true) != Case.No);

            using (var args = new FunctionWrapper(fg,
                                                  $"public{overrideStr}IEnumerable<{nameof(IMajorRecordCommon)}{(getter ? "Getter" : null)}> EnumerateMajorRecords"))
            {
                args.Add($"{obj.Interface(getter: getter, internalInterface: true)} obj");
            }
            using (new BraceWrapper(fg))
            {
                if (setter)
                {
                    fg.AppendLine($"foreach (var item in {obj.CommonClass(LoquiInterfaceType.IGetter, CommonGenerics.Class)}.Instance.EnumerateMajorRecords(obj))");
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine($"yield return (item as {nameof(IMajorRecordCommon)})!;");
                    }
                }
                else
                {
                    var fgCount = fg.Count;
                    foreach (var baseClass in obj.BaseClassTrail())
                    {
                        if (await MajorRecordModule.HasMajorRecords(baseClass, includeBaseClass: true, includeSelf: true) != Case.No)
                        {
                            fg.AppendLine("foreach (var item in base.EnumerateMajorRecords(obj))");
                            using (new BraceWrapper(fg))
                            {
                                fg.AppendLine("yield return item;");
                            }
                            break;
                        }
                    }
                    foreach (var field in obj.IterateFields())
                    {
                        switch (field)
                        {
                        case LoquiType _:
                        case ContainerType _:
                        case DictType _:
                            break;

                        default:
                            continue;
                        }

                        FileGeneration fieldFg = new FileGeneration();
                        if (field is LoquiType loqui)
                        {
                            var isMajorRecord = loqui.TargetObjectGeneration != null && await loqui.TargetObjectGeneration.IsMajorRecord();

                            if (isMajorRecord ||
                                await MajorRecordModule.HasMajorRecords(loqui, includeBaseClass: true) != Case.No)
                            {
                                var subFg         = new FileGeneration();
                                var fieldAccessor = loqui.Nullable ? $"{loqui.Name}item" : $"{accessor}.{loqui.Name}";
                                await LoquiTypeHandler(subFg, fieldAccessor, loqui, generic : null, checkType : false);

                                if (subFg.Count == 0)
                                {
                                    continue;
                                }
                                if (loqui.Singleton ||
                                    !loqui.Nullable)
                                {
                                    fieldFg.AppendLines(subFg);
                                }
                                else
                                {
                                    fieldFg.AppendLine($"if ({accessor}.{loqui.Name}.TryGet(out var {loqui.Name}item))");
                                    using (new BraceWrapper(fieldFg))
                                    {
                                        fieldFg.AppendLines(subFg);
                                    }
                                }
                            }
                        }
                        else if (field is ContainerType cont)
                        {
                            if (!(cont.SubTypeGeneration is LoquiType contLoqui))
                            {
                                continue;
                            }
                            var isMajorRecord = contLoqui.TargetObjectGeneration != null && await contLoqui.TargetObjectGeneration.IsMajorRecord();

                            if (isMajorRecord ||
                                await MajorRecordModule.HasMajorRecords(contLoqui, includeBaseClass: true) != Case.No)
                            {
                                switch (await MajorRecordModule.HasMajorRecords(contLoqui, includeBaseClass: true))
                                {
                                case Case.Yes:
                                    fieldFg.AppendLine($"foreach (var subItem in {accessor}.{field.Name}{(field.Nullable ? ".EmptyIfNull()" : null)})");
                                    using (new BraceWrapper(fieldFg))
                                    {
                                        await LoquiTypeHandler(fieldFg, $"subItem", contLoqui, generic : null, checkType : false);
                                    }
                                    break;

                                case Case.Maybe:
                                    fieldFg.AppendLine($"foreach (var subItem in {accessor}.{field.Name}{(field.Nullable ? ".EmptyIfNull()" : null)}.WhereCastable<{contLoqui.TypeName(getter: false)}, {(getter ? nameof(IMajorRecordGetterEnumerable) : nameof(IMajorRecordEnumerable))}>())");
                                    using (new BraceWrapper(fieldFg))
                                    {
                                        await LoquiTypeHandler(fieldFg, $"subItem", contLoqui, generic : null, checkType : false);
                                    }
                                    break;

                                case Case.No:
                                default:
                                    break;
                                }
                            }
                        }
                        else if (field is DictType dict)
                        {
                            if (dict.Mode != DictMode.KeyedValue)
                            {
                                continue;
                            }
                            if (!(dict.ValueTypeGen is LoquiType dictLoqui))
                            {
                                continue;
                            }
                            var isMajorRecord = dictLoqui.TargetObjectGeneration != null && await dictLoqui.TargetObjectGeneration.IsMajorRecord();

                            if (isMajorRecord ||
                                await MajorRecordModule.HasMajorRecords(dictLoqui, includeBaseClass: true) != Case.No)
                            {
                                switch (await MajorRecordModule.HasMajorRecords(dictLoqui, includeBaseClass: true))
                                {
                                case Case.Yes:
                                    fieldFg.AppendLine($"foreach (var subItem in {accessor}.{field.Name}.Items)");
                                    using (new BraceWrapper(fieldFg))
                                    {
                                        await LoquiTypeHandler(fieldFg, $"subItem", dictLoqui, generic : null, checkType : false);
                                    }
                                    break;

                                case Case.Maybe:
                                    fieldFg.AppendLine($"foreach (var subItem in {accessor}.{field.Name}.Items.WhereCastable<{dictLoqui.TypeName(getter: false)}, {(getter ? nameof(IMajorRecordGetterEnumerable) : nameof(IMajorRecordEnumerable))}>())");
                                    using (new BraceWrapper(fieldFg))
                                    {
                                        await LoquiTypeHandler(fieldFg, $"subItem", dictLoqui, generic : null, checkType : false);
                                    }
                                    break;

                                case Case.No:
                                default:
                                    break;
                                }
                            }
                        }

                        if (fieldFg.Count > 0)
                        {
                            if (field.Nullable)
                            {
                                fg.AppendLine($"if ({field.NullableAccessor(getter: true, Accessor.FromType(field, accessor.ToString()))})");
                            }
                            using (new BraceWrapper(fg, doIt: field.Nullable))
                            {
                                fg.AppendLines(fieldFg);
                            }
                        }
                    }
                    if (fgCount == fg.Count)
                    {
                        fg.AppendLine("yield break;");
                    }
                }
            }
            fg.AppendLine();

            // Generate base overrides
            foreach (var baseClass in obj.BaseClassTrail())
            {
                if (await MajorRecordModule.HasMajorRecords(baseClass, includeBaseClass: true, includeSelf: true) != Case.No)
                {
                    using (var args = new FunctionWrapper(fg,
                                                          $"public override IEnumerable<{nameof(IMajorRecordCommon)}{(getter ? "Getter" : null)}> EnumerateMajorRecords"))
                    {
                        args.Add($"{baseClass.Interface(getter: getter)} obj");
                    }
                    using (new BraceWrapper(fg))
                    {
                        using (var args = new ArgsWrapper(fg,
                                                          "EnumerateMajorRecords"))
                        {
                            args.Add($"({obj.Interface(getter: getter)})obj");
                        }
                    }
                    fg.AppendLine();
                }
            }

            using (var args = new FunctionWrapper(fg,
                                                  $"public{overrideStr}IEnumerable<{nameof(IMajorRecordCommonGetter)}> EnumeratePotentiallyTypedMajorRecords"))
            {
                args.Add($"{obj.Interface(getter: getter, internalInterface: true)} obj");
                args.Add($"Type? type");
                args.Add($"bool throwIfUnknown");
            }
            using (new BraceWrapper(fg))
            {
                fg.AppendLine("if (type == null) return EnumerateMajorRecords(obj);");
                fg.AppendLine("return EnumerateMajorRecords(obj, type, throwIfUnknown);");
            }
            fg.AppendLine();

            using (var args = new FunctionWrapper(fg,
                                                  $"public{overrideStr}IEnumerable<{nameof(IMajorRecordCommonGetter)}> EnumerateMajorRecords"))
            {
                args.Add($"{obj.Interface(getter: getter, internalInterface: true)} obj");
                args.Add($"Type type");
                args.Add($"bool throwIfUnknown");
            }
            using (new BraceWrapper(fg))
            {
                if (setter)
                {
                    fg.AppendLine($"foreach (var item in {obj.CommonClass(LoquiInterfaceType.IGetter, CommonGenerics.Class)}.Instance.EnumerateMajorRecords(obj, type, throwIfUnknown))");
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine("yield return item;");
                    }
                }
                else
                {
                    var fgCount = fg.Count;
                    foreach (var baseClass in obj.BaseClassTrail())
                    {
                        if (await MajorRecordModule.HasMajorRecords(baseClass, includeBaseClass: true, includeSelf: true) != Case.No)
                        {
                            fg.AppendLine("foreach (var item in base.EnumerateMajorRecords<TMajor>(obj))");
                            using (new BraceWrapper(fg))
                            {
                                fg.AppendLine("yield return item;");
                            }
                            break;
                        }
                    }

                    fg.AppendLine("switch (type.Name)");
                    using (new BraceWrapper(fg))
                    {
                        var gameCategory = obj.GetObjectData().GameCategory;
                        fg.AppendLine($"case \"{nameof(IMajorRecordCommon)}\":");
                        fg.AppendLine($"case \"{nameof(IMajorRecord)}\":");
                        fg.AppendLine($"case \"{nameof(MajorRecord)}\":");
                        if (gameCategory != null)
                        {
                            fg.AppendLine($"case \"I{gameCategory}MajorRecord\":");
                            fg.AppendLine($"case \"{gameCategory}MajorRecord\":");
                        }
                        using (new DepthWrapper(fg))
                        {
                            fg.AppendLine($"if (!{obj.RegistrationName}.SetterType.IsAssignableFrom(obj.GetType())) yield break;");
                            fg.AppendLine("foreach (var item in this.EnumerateMajorRecords(obj))");
                            using (new BraceWrapper(fg))
                            {
                                fg.AppendLine("yield return item;");
                            }
                            fg.AppendLine("yield break;");
                        }
                        fg.AppendLine($"case \"{nameof(IMajorRecordGetter)}\":");
                        fg.AppendLine($"case \"{nameof(IMajorRecordCommonGetter)}\":");
                        if (gameCategory != null)
                        {
                            fg.AppendLine($"case \"I{gameCategory}MajorRecordGetter\":");
                        }
                        using (new DepthWrapper(fg))
                        {
                            fg.AppendLine("foreach (var item in this.EnumerateMajorRecords(obj))");
                            using (new BraceWrapper(fg))
                            {
                                fg.AppendLine("yield return item;");
                            }
                            fg.AppendLine("yield break;");
                        }

                        Dictionary <object, FileGeneration> generationDict = new Dictionary <object, FileGeneration>();
                        foreach (var field in obj.IterateFields())
                        {
                            FileGeneration fieldGen;
                            if (field is LoquiType loqui)
                            {
                                if (loqui.TargetObjectGeneration.IsListGroup())
                                {
                                    continue;
                                }
                                var isMajorRecord = loqui.TargetObjectGeneration != null && await loqui.TargetObjectGeneration.IsMajorRecord();

                                if (!isMajorRecord &&
                                    await MajorRecordModule.HasMajorRecords(loqui, includeBaseClass: true) == Case.No)
                                {
                                    continue;
                                }

                                if (loqui.TargetObjectGeneration.GetObjectType() == ObjectType.Group)
                                {
                                    fieldGen = generationDict.GetOrAdd(loqui.GetGroupTarget());
                                }
                                else
                                {
                                    fieldGen = generationDict.GetOrAdd(((object)loqui?.TargetObjectGeneration) ?? loqui);
                                }
                            }
                            else if (field is ContainerType cont)
                            {
                                if (!(cont.SubTypeGeneration is LoquiType contLoqui))
                                {
                                    continue;
                                }
                                if (contLoqui.RefType == LoquiType.LoquiRefType.Generic)
                                {
                                    fieldGen = generationDict.GetOrAdd("default:");
                                }
                                else
                                {
                                    fieldGen = generationDict.GetOrAdd(((object)contLoqui?.TargetObjectGeneration) ?? contLoqui);
                                }
                            }
                            else if (field is DictType dict)
                            {
                                if (dict.Mode != DictMode.KeyedValue)
                                {
                                    continue;
                                }
                                if (!(dict.ValueTypeGen is LoquiType dictLoqui))
                                {
                                    continue;
                                }
                                if (dictLoqui.RefType == LoquiType.LoquiRefType.Generic)
                                {
                                    fieldGen = generationDict.GetOrAdd("default:");
                                }
                                else
                                {
                                    fieldGen = generationDict.GetOrAdd(((object)dictLoqui?.TargetObjectGeneration) ?? dictLoqui);
                                }
                            }
                            else
                            {
                                continue;
                            }
                            await ApplyIterationLines(field, fieldGen, accessor, getter);
                        }

                        bool doAdditionlDeepLogic = obj.Name != "ListGroup";

                        if (doAdditionlDeepLogic)
                        {
                            var deepRecordMapping = await MajorRecordModule.FindDeepRecords(obj);

                            foreach (var deepRec in deepRecordMapping)
                            {
                                FileGeneration deepFg = generationDict.GetOrAdd(deepRec.Key);
                                foreach (var field in deepRec.Value)
                                {
                                    await ApplyIterationLines(field, deepFg, accessor, getter, targetObj : deepRec.Key);
                                }
                            }

                            HashSet <string> blackList = new HashSet <string>();
                            foreach (var kv in generationDict)
                            {
                                switch (kv.Key)
                                {
                                case LoquiType loqui:
                                    if (loqui.RefType == LoquiType.LoquiRefType.Generic)
                                    {
                                        // Handled in default case
                                        continue;
                                    }
                                    else
                                    {
                                        fg.AppendLine($"case \"{loqui.Interface(getter: true)}\":");
                                        fg.AppendLine($"case \"{loqui.Interface(getter: false)}\":");
                                        if (loqui.HasInternalGetInterface)
                                        {
                                            fg.AppendLine($"case \"{loqui.Interface(getter: true, internalInterface: true)}\":");
                                        }
                                        if (loqui.HasInternalSetInterface)
                                        {
                                            fg.AppendLine($"case \"{loqui.Interface(getter: false, internalInterface: true)}\":");
                                        }
                                        if (loqui.RefType == LoquiType.LoquiRefType.Interface)
                                        {
                                            blackList.Add(loqui.SetterInterface);
                                        }
                                    }
                                    break;

                                case ObjectGeneration targetObj:
                                    fg.AppendLine($"case \"{targetObj.ObjectName}\":");
                                    fg.AppendLine($"case \"{targetObj.Interface(getter: true)}\":");
                                    fg.AppendLine($"case \"{targetObj.Interface(getter: false)}\":");
                                    if (targetObj.HasInternalGetInterface)
                                    {
                                        fg.AppendLine($"case \"{targetObj.Interface(getter: true, internalInterface: true)}\":");
                                    }
                                    if (targetObj.HasInternalSetInterface)
                                    {
                                        fg.AppendLine($"case \"{targetObj.Interface(getter: false, internalInterface: true)}\":");
                                    }
                                    break;

                                case string str:
                                    if (str != "default:")
                                    {
                                        throw new NotImplementedException();
                                    }
                                    continue;

                                default:
                                    throw new NotImplementedException();
                                }
                                using (new DepthWrapper(fg))
                                {
                                    fg.AppendLines(kv.Value);
                                    fg.AppendLine("yield break;");
                                }
                            }

                            // Generate for major record marker interfaces
                            if (LinkInterfaceModule.ObjectMappings.TryGetValue(obj.ProtoGen.Protocol, out var interfs))
                            {
                                foreach (var interf in interfs)
                                {
                                    if (blackList.Contains(interf.Key))
                                    {
                                        continue;
                                    }
                                    FileGeneration             subFg         = new FileGeneration();
                                    HashSet <ObjectGeneration> passedObjects = new HashSet <ObjectGeneration>();
                                    HashSet <TypeGeneration>   deepObjects   = new HashSet <TypeGeneration>();
                                    foreach (var subObj in interf.Value)
                                    {
                                        var grup = obj.Fields
                                                   .WhereCastable <TypeGeneration, GroupType>()
                                                   .Where(g => g.GetGroupTarget() == subObj)
                                                   .FirstOrDefault();

                                        if (grup != null)
                                        {
                                            subFg.AppendLine($"foreach (var item in EnumerateMajorRecords({accessor}, typeof({grup.GetGroupTarget().Interface(getter: true)}), throwIfUnknown: throwIfUnknown))");
                                            using (new BraceWrapper(subFg))
                                            {
                                                subFg.AppendLine("yield return item;");
                                            }
                                            passedObjects.Add(grup.GetGroupTarget());
                                        }
                                        else if (deepRecordMapping.TryGetValue(subObj, out var deepRec))
                                        {
                                            foreach (var field in deepRec)
                                            {
                                                deepObjects.Add(field);
                                            }
                                        }
                                    }
                                    foreach (var deepObj in deepObjects)
                                    {
                                        await ApplyIterationLines(deepObj, subFg, accessor, getter, blackList : passedObjects);
                                    }
                                    if (!subFg.Empty)
                                    {
                                        fg.AppendLine($"case \"{interf.Key}\":");
                                        using (new BraceWrapper(fg))
                                        {
                                            fg.AppendLine($"if (!{obj.RegistrationName}.SetterType.IsAssignableFrom(obj.GetType())) yield break;");
                                            fg.AppendLines(subFg);
                                            fg.AppendLine("yield break;");
                                        }
                                        fg.AppendLine($"case \"{interf.Key}Getter\":");
                                        using (new BraceWrapper(fg))
                                        {
                                            fg.AppendLines(subFg);
                                            fg.AppendLine("yield break;");
                                        }
                                    }
                                }
                            }
                        }

                        fg.AppendLine("default:");
                        using (new DepthWrapper(fg))
                        {
                            if (generationDict.TryGetValue("default:", out var gen))
                            {
                                fg.AppendLines(gen);
                                fg.AppendLine("yield break;");
                            }
                            else
                            {
                                fg.AppendLine("if (throwIfUnknown)");
                                using (new BraceWrapper(fg))
                                {
                                    fg.AppendLine("throw new ArgumentException($\"Unknown major record type: {type}\");");
                                }
                                fg.AppendLine($"else");
                                using (new BraceWrapper(fg))
                                {
                                    fg.AppendLine("yield break;");
                                }
                            }
                        }
                    }
                }
            }
            fg.AppendLine();

            // Generate base overrides
            foreach (var baseClass in obj.BaseClassTrail())
            {
                if (await MajorRecordModule.HasMajorRecords(baseClass, includeBaseClass: true, includeSelf: true) != Case.No)
                {
                    using (var args = new FunctionWrapper(fg,
                                                          $"public override IEnumerable<TMajor> EnumerateMajorRecords<TMajor>"))
                    {
                        args.Add($"{baseClass.Interface(getter: getter)} obj");
                        args.Wheres.Add($"where TMajor : {nameof(IMajorRecordCommon)}{(getter ? "Getter" : null)}");
                    }
                    using (new BraceWrapper(fg))
                    {
                        using (var args = new ArgsWrapper(fg,
                                                          "EnumerateMajorRecords<TMajor>"))
                        {
                            args.Add($"({obj.Interface(getter: getter)})obj");
                        }
                    }
                    fg.AppendLine();
                }
            }
        }
Ejemplo n.º 17
0
        public override async Task GenerateInCommonMixin(ObjectGeneration obj, FileGeneration fg)
        {
            if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No)
            {
                return;
            }
            var    needsCatch = obj.GetObjectType() == ObjectType.Mod;
            string catchLine  = needsCatch ? ".Catch(e => throw RecordException.Enrich(e, obj.ModKey))" : string.Empty;
            string enderSemi  = needsCatch ? string.Empty : ";";

            fg.AppendLine("[DebuggerStepThrough]");
            using (var args = new FunctionWrapper(fg,
                                                  $"public static IEnumerable<{nameof(IMajorRecordCommonGetter)}> EnumerateMajorRecords{obj.GetGenericTypes(MaskType.Normal)}"))
            {
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.IGetter, obj.Generics));
                args.Add($"this {obj.Interface(getter: true, internalInterface: true)} obj");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new ArgsWrapper(fg,
                                                  $"return {obj.CommonClassInstance("obj", LoquiInterfaceType.IGetter, CommonGenerics.Class)}.EnumerateMajorRecords",
                                                  suffixLine: catchLine))
                {
                    args.AddPassArg("obj");
                }
            }
            fg.AppendLine();

            fg.AppendLine("[DebuggerStepThrough]");
            using (var args = new FunctionWrapper(fg,
                                                  $"public static IEnumerable<TMajor> EnumerateMajorRecords{obj.GetGenericTypes(MaskType.Normal, "TMajor")}"))
            {
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.IGetter, obj.Generics));
                args.Wheres.Add($"where TMajor : class, IMajorRecordCommonGetter");
                args.Add($"this {obj.Interface(getter: true, internalInterface: true)} obj");
                args.Add($"bool throwIfUnknown = true");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new FunctionWrapper(fg,
                                                      $"return {obj.CommonClassInstance("obj", LoquiInterfaceType.IGetter, CommonGenerics.Class)}.EnumerateMajorRecords"))
                {
                    args.AddPassArg("obj");
                    args.Add("type: typeof(TMajor)");
                    args.AddPassArg("throwIfUnknown");
                }
                using (new DepthWrapper(fg))
                {
                    fg.AppendLine($".Select(m => (TMajor)m){enderSemi}");
                    if (needsCatch)
                    {
                        fg.AppendLine($"{catchLine};");
                    }
                }
            }
            fg.AppendLine();

            fg.AppendLine("[DebuggerStepThrough]");
            using (var args = new FunctionWrapper(fg,
                                                  $"public static IEnumerable<{nameof(IMajorRecordCommonGetter)}> EnumerateMajorRecords{obj.GetGenericTypes(MaskType.Normal)}"))
            {
                args.Add($"this {obj.Interface(getter: true, internalInterface: true)} obj");
                args.Add($"Type type");
                args.Add($"bool throwIfUnknown = true");
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.IGetter, obj.Generics));
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new FunctionWrapper(fg,
                                                      $"return {obj.CommonClassInstance("obj", LoquiInterfaceType.IGetter, CommonGenerics.Class)}.EnumerateMajorRecords"))
                {
                    args.AddPassArg("obj");
                    args.AddPassArg("type");
                    args.AddPassArg("throwIfUnknown");
                }
                using (new DepthWrapper(fg))
                {
                    fg.AppendLine($".Select(m => ({nameof(IMajorRecordCommonGetter)})m){enderSemi}");
                    if (needsCatch)
                    {
                        fg.AppendLine($"{catchLine};");
                    }
                }
            }
            fg.AppendLine();

            fg.AppendLine("[DebuggerStepThrough]");
            using (var args = new FunctionWrapper(fg,
                                                  $"public static IEnumerable<{nameof(IMajorRecordCommon)}> EnumerateMajorRecords{obj.GetGenericTypes(MaskType.Normal)}"))
            {
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics));
                args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new ArgsWrapper(fg,
                                                  $"return {obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.EnumerateMajorRecords",
                                                  suffixLine: catchLine))
                {
                    args.AddPassArg("obj");
                }
            }
            fg.AppendLine();

            fg.AppendLine("[DebuggerStepThrough]");
            using (var args = new FunctionWrapper(fg,
                                                  $"public static IEnumerable<TMajor> EnumerateMajorRecords{obj.GetGenericTypes(MaskType.Normal, "TMajor")}"))
            {
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics));
                args.Wheres.Add($"where TMajor : class, IMajorRecordCommon");
                args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new FunctionWrapper(fg,
                                                      $"return {obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.EnumerateMajorRecords"))
                {
                    args.AddPassArg("obj");
                    args.Add("type: typeof(TMajor)");
                    args.Add("throwIfUnknown: true");
                }
                using (new DepthWrapper(fg))
                {
                    fg.AppendLine($".Select(m => (TMajor)m){enderSemi}");
                    if (needsCatch)
                    {
                        fg.AppendLine($"{catchLine};");
                    }
                }
            }
            fg.AppendLine();

            fg.AppendLine("[DebuggerStepThrough]");
            using (var args = new FunctionWrapper(fg,
                                                  $"public static IEnumerable<{nameof(IMajorRecordCommon)}> EnumerateMajorRecords{obj.GetGenericTypes(MaskType.Normal)}"))
            {
                args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj");
                args.Add($"Type? type");
                args.Add($"bool throwIfUnknown = true");
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics));
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new FunctionWrapper(fg,
                                                      $"return {obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.EnumeratePotentiallyTypedMajorRecords"))
                {
                    args.AddPassArg("obj");
                    args.AddPassArg("type");
                    args.AddPassArg("throwIfUnknown");
                }
                using (new DepthWrapper(fg))
                {
                    fg.AppendLine($".Select(m => ({nameof(IMajorRecordCommon)})m){enderSemi}");
                    if (needsCatch)
                    {
                        fg.AppendLine($"{catchLine};");
                    }
                }
            }
            fg.AppendLine();
        }
Ejemplo n.º 18
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.º 19
0
        protected override void FillPublicElement(ObjectGeneration obj, FileGeneration fg)
        {
            using (var args = new FunctionWrapper(fg,
                                                  $"public static void FillPublicElement{ModuleNickname}"))
            {
                args.Add($"{obj.Interface(getter: false, internalInterface: true)} item");
                args.Add($"XElement {XmlTranslationModule.XElementLine.GetParameterName(obj)}");
                args.Add("string name");
                args.Add($"ErrorMaskBuilder? errorMask");
                args.Add($"{nameof(TranslationCrystal)}? translationMask");
            }
            using (new BraceWrapper(fg))
            {
                fg.AppendLine("switch (name)");
                using (new BraceWrapper(fg))
                {
                    bool isInRange = false;
                    foreach (var field in obj.IterateFields(expandSets: SetMarkerType.ExpandSets.FalseAndInclude, nonIntegrated: true))
                    {
                        if (field is DataType set)
                        {
                            foreach (var subField in set.IterateFieldsWithMeta())
                            {
                                if (subField.Field.Derivative)
                                {
                                    continue;
                                }
                                if (subField.Field.ReadOnly)
                                {
                                    continue;
                                }
                                if (!subField.Field.IntegrateField)
                                {
                                    continue;
                                }
                                if (!this.TryGetTypeGeneration(subField.Field.GetType(), out var generator))
                                {
                                    throw new ArgumentException("Unsupported type generator: " + subField.Field);
                                }

                                fg.AppendLine($"case \"{subField.Field.Name}\":");
                                using (new DepthWrapper(fg))
                                {
                                    if (generator.ShouldGenerateCopyIn(subField.Field))
                                    {
                                        generator.GenerateCopyIn(
                                            fg: fg,
                                            objGen: obj,
                                            typeGen: subField.Field,
                                            nodeAccessor: XmlTranslationModule.XElementLine.GetParameterName(obj).Result,
                                            itemAccessor: Accessor.FromType(subField.Field, "item"),
                                            translationMaskAccessor: "translationMask",
                                            errorMaskAccessor: $"errorMask");
                                    }
                                    HandleDataTypeParsing(obj, fg, set, subField, ref isInRange);
                                    fg.AppendLine("break;");
                                }
                            }
                        }
                        else if (field.IntegrateField)
                        {
                            if (field.Derivative)
                            {
                                continue;
                            }
                            if (field.ReadOnly)
                            {
                                continue;
                            }
                            if (!this.TryGetTypeGeneration(field.GetType(), out var generator))
                            {
                                throw new ArgumentException("Unsupported type generator: " + field);
                            }

                            fg.AppendLine($"case \"{field.Name}\":");
                            using (new DepthWrapper(fg))
                            {
                                if (generator.ShouldGenerateCopyIn(field))
                                {
                                    generator.GenerateCopyIn(
                                        fg: fg,
                                        objGen: obj,
                                        typeGen: field,
                                        nodeAccessor: XmlTranslationModule.XElementLine.GetParameterName(obj).Result,
                                        itemAccessor: Accessor.FromType(field, "item"),
                                        translationMaskAccessor: "translationMask",
                                        errorMaskAccessor: $"errorMask");
                                }
                                fg.AppendLine("break;");
                            }
                        }
                    }

                    fg.AppendLine("default:");
                    using (new DepthWrapper(fg))
                    {
                        if (obj.HasLoquiBaseObject)
                        {
                            using (var args = new ArgsWrapper(fg,
                                                              $"{this.TranslationCreateClass(obj.BaseClass)}.FillPublicElement{ModuleNickname}"))
                            {
                                args.Add("item: item");
                                args.Add($"{XmlTranslationModule.XElementLine.GetParameterName(obj)}: {XmlTranslationModule.XElementLine.GetParameterName(obj)}");
                                args.Add("name: name");
                                args.Add("errorMask: errorMask");
                                if (this.TranslationMaskParameter)
                                {
                                    args.Add($"translationMask: translationMask");
                                }
                            }
                        }
                        fg.AppendLine("break;");
                    }
                }
            }
            fg.AppendLine();
        }
Ejemplo n.º 20
0
        public override async Task GenerateInCommon(ObjectGeneration obj, FileGeneration fg, MaskTypeSet maskTypes)
        {
            if (!maskTypes.Applicable(LoquiInterfaceType.IGetter, CommonGenerics.Class))
            {
                return;
            }
            await base.GenerateInCommon(obj, fg, maskTypes);

            if (!await obj.IsMajorRecord())
            {
                return;
            }
            using (new RegionWrapper(fg, "Duplicate"))
            {
                using (var args = new FunctionWrapper(fg,
                                                      $"public{obj.Virtual()}{obj.Name} Duplicate{obj.GetGenericTypes(MaskType.Normal, MaskType.NormalGetter)}"))
                {
                    args.Wheres.AddRange(obj.GenericTypeMaskWheres(LoquiInterfaceType.IGetter, MaskType.Normal, MaskType.NormalGetter));
                    args.Add($"{obj.Interface(getter: true)} item");
                    args.Add($"{nameof(FormKey)} formKey");
                    args.Add($"TranslationCrystal? copyMask");
                }
                using (new BraceWrapper(fg))
                {
                    if (obj.Abstract)
                    {
                        fg.AppendLine("throw new NotImplementedException();");
                    }
                    else
                    {
                        fg.AppendLine($"var newRec = new {obj.Name}(formKey{(obj.GetObjectData().HasMultipleReleases ? $", default({obj.GetObjectData().GameCategory}Release)" : null)});");
                        fg.AppendLine($"newRec.DeepCopyIn(item, default({nameof(ErrorMaskBuilder)}?), copyMask);");
                        fg.AppendLine("return newRec;");
                    }
                }
                fg.AppendLine();

                foreach (var baseClass in obj.BaseClassTrail())
                {
                    using (var args = new FunctionWrapper(fg,
                                                          $"public override {baseClass.Name} Duplicate{baseClass.GetGenericTypes(MaskType.Normal, MaskType.NormalGetter)}"))
                    {
                        args.Wheres.AddRange(baseClass.GenericTypeMaskWheres(LoquiInterfaceType.IGetter, MaskType.Normal, MaskType.NormalGetter));
                        args.Add($"{baseClass.Interface(getter: true)} item");
                        args.Add($"{nameof(FormKey)} formKey");
                        args.Add($"TranslationCrystal? copyMask");
                    }
                    using (new BraceWrapper(fg))
                    {
                        using (var args = new ArgsWrapper(fg,
                                                          $"return this.Duplicate"))
                        {
                            args.Add($"item: ({obj.Interface(getter: false)})item");
                            args.AddPassArg("formKey");
                            args.AddPassArg("copyMask");
                        }
                    }
                    fg.AppendLine();
                }
            }
        }
Ejemplo n.º 21
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.º 22
0
        private async Task GenerateForMod(ObjectGeneration obj, FileGeneration fg)
        {
            using (var args = new FunctionWrapper(fg,
                                                  $"public static Task<{obj.Name}> CreateFromXmlFolder"))
            {
                args.Add("DirectoryPath dir");
                args.Add("ModKey modKey");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new ArgsWrapper(fg,
                                                  "return CreateFromXmlFolder"))
                {
                    args.Add("dir: dir");
                    args.Add("modKey: modKey");
                    args.Add("errorMask: null");
                }
            }
            fg.AppendLine();

            using (var args = new FunctionWrapper(fg,
                                                  $"public static async Task<({obj.Name} Mod, {obj.Mask(MaskType.Error)} ErrorMask)> CreateFromXmlFolderWithErrorMask"))
            {
                args.Add("DirectoryPath dir");
                args.Add("ModKey modKey");
            }
            using (new BraceWrapper(fg))
            {
                fg.AppendLine("ErrorMaskBuilder? errorMaskBuilder = new ErrorMaskBuilder();");
                using (var args = new ArgsWrapper(fg,
                                                  "var ret = await CreateFromXmlFolder"))
                {
                    args.Add("dir: dir");
                    args.Add("modKey: modKey");
                    args.Add("errorMask: errorMaskBuilder");
                }
                fg.AppendLine($"var errorMask = {obj.Mask(MaskType.Error)}.Factory(errorMaskBuilder);");
                fg.AppendLine("return (ret, errorMask);");
            }
            fg.AppendLine();

            using (var args = new FunctionWrapper(fg,
                                                  $"public static async Task<{obj.Name}> CreateFromXmlFolder"))
            {
                args.Add("DirectoryPath dir");
                args.Add("ModKey modKey");
                args.Add("ErrorMaskBuilder? errorMask");
            }
            using (new BraceWrapper(fg))
            {
                fg.AppendLine($"var item = new {obj.Name}(modKey);");
                fg.AppendLine($"var tasks = new List<Task>();");
                foreach (var field in obj.IterateFields())
                {
                    if (field.GetFieldData().CustomFolder)
                    {
                        using (var args = new ArgsWrapper(fg,
                                                          $"tasks.Add(Task.Run(() => item.CreateFromXmlFolder{field.Name}",
                                                          suffixLine: "))"))
                        {
                            args.Add("dir: dir");
                            args.Add($"name: nameof({field.Name})");
                            args.Add($"index: (int){field.IndexEnumName}");
                            args.Add($"errorMask: errorMask");
                        }
                        continue;
                    }
                    if (!(field is LoquiType loqui))
                    {
                        throw new ArgumentException();
                    }
                    switch (loqui.TargetObjectGeneration.GetObjectType())
                    {
                    case ObjectType.Record:
                        using (var args = new ArgsWrapper(fg,
                                                          $"item.{field.Name}.CopyInFromXml"))
                        {
                            args.Add($"path: Path.Combine(dir.Path, \"{field.Name}.xml\")");
                            args.Add($"errorMask: errorMask");
                            args.Add($"translationMask: null");
                        }
                        break;

                    case ObjectType.Group:
                        if (!loqui.TryGetSpecificationAsObject("T", out var subObj))
                        {
                            continue;
                        }
                        using (var args = new ArgsWrapper(fg,
                                                          $"tasks.Add(Task.Run(() => item.{field.Name}.CreateFromXmlFolder<{subObj.Name}>",
                                                          suffixLine: "))"))
                        {
                            args.Add($"dir: dir");
                            args.Add($"name: nameof({field.Name})");
                            args.Add($"errorMask: errorMask");
                            args.Add($"index: (int){field.IndexEnumName}");
                        }
                        break;

                    default:
                        break;
                    }
                }
                fg.AppendLine("await Task.WhenAll(tasks);");
                fg.AppendLine("return item;");
            }
            fg.AppendLine();

            using (var args = new FunctionWrapper(fg,
                                                  $"public async Task<{obj.Mask(MaskType.Error)}?> WriteToXmlFolder"))
            {
                args.Add("DirectoryPath dir");
                args.Add("bool doMasks = true");
            }
            using (new BraceWrapper(fg))
            {
                fg.AppendLine($"ErrorMaskBuilder? errorMaskBuilder = null;");
                fg.AppendLine("dir.Create();");
                fg.AppendLine("using (new FolderCleaner(dir, FolderCleaner.CleanType.AccessTime))");
                using (new BraceWrapper(fg))
                {
                    fg.AppendLine($"var tasks = new List<Task>();");
                    foreach (var field in obj.IterateFields())
                    {
                        if (!(field is LoquiType loqui))
                        {
                            throw new ArgumentException();
                        }
                        if (field.GetFieldData().CustomFolder)
                        {
                            using (var args = new ArgsWrapper(fg,
                                                              $"tasks.Add(Task.Run(() => WriteToXmlFolder{field.Name}",
                                                              suffixLine: "))"))
                            {
                                args.Add("dir: dir");
                                args.Add($"name: nameof({field.Name})");;
                                args.Add($"index: (int){field.IndexEnumName}");
                                args.Add($"errorMask: errorMaskBuilder");
                            }
                            continue;
                        }
                        switch (loqui.TargetObjectGeneration.GetObjectType())
                        {
                        case ObjectType.Record:
                            using (var args = new ArgsWrapper(fg,
                                                              $"tasks.Add(Task.Run(() => this.{field.Name}.WriteToXml",
                                                              suffixLine: "))"))
                            {
                                args.Add($"path: Path.Combine(dir.Path, \"{field.Name}.xml\")");
                                args.Add($"errorMask: errorMaskBuilder");
                                args.Add($"translationMask: null");
                            }
                            break;

                        case ObjectType.Group:
                            ObjectGeneration subObj;
                            if (field is GroupType group)
                            {
                                if (!group.TryGetSpecificationAsObject("T", out subObj))
                                {
                                    continue;
                                }
                                using (var args = new ArgsWrapper(fg,
                                                                  $"tasks.Add(Task.Run(() => {field.Name}.WriteToXmlFolder<{subObj.Name}, {subObj.Mask(MaskType.Error)}>",
                                                                  suffixLine: "))"))
                                {
                                    args.Add($"dir: dir.Path");
                                    args.Add($"name: nameof({field.Name})");
                                    args.Add($"errorMask: errorMaskBuilder");
                                    args.Add($"index: (int){field.IndexEnumName}");
                                }
                            }
                            else
                            {
                                using (var args = new ArgsWrapper(fg,
                                                                  $"tasks.Add(Task.Run(() => {field.Name}.WriteToXmlFolder",
                                                                  suffixLine: "))"))
                                {
                                    args.Add($"dir: dir.Path");
                                    args.Add($"name: nameof({field.Name})");
                                    args.Add($"errorMask: errorMaskBuilder");
                                    args.Add($"index: (int){field.IndexEnumName}");
                                }
                            }
                            break;

                        default:
                            break;
                        }
                    }
                    fg.AppendLine("await Task.WhenAll(tasks);");
                }
                fg.AppendLine("return null;");
            }
        }
        public override async Task GenerateInCommonMixin(ObjectGeneration obj, FileGeneration fg)
        {
            if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No)
            {
                return;
            }
            fg.AppendLine("[DebuggerStepThrough]");
            using (var args = new FunctionWrapper(fg,
                                                  $"public static void Remove{obj.GetGenericTypes(MaskType.Normal)}"))
            {
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics));
                args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj");
                args.Add($"{nameof(FormKey)} key");
            }
            using (new BraceWrapper(fg))
            {
                fg.AppendLine($"var keys = new HashSet<{nameof(FormKey)}>();");
                fg.AppendLine("keys.Add(key);");
                using (var args = new ArgsWrapper(fg,
                                                  $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove"))
                {
                    args.AddPassArg("obj");
                    args.AddPassArg("keys");
                }
            }
            fg.AppendLine();

            if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No)
            {
                return;
            }
            fg.AppendLine("[DebuggerStepThrough]");
            using (var args = new FunctionWrapper(fg,
                                                  $"public static void Remove{obj.GetGenericTypes(MaskType.Normal)}"))
            {
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics));
                args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj");
                args.Add($"IEnumerable<{nameof(FormKey)}> keys");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new ArgsWrapper(fg,
                                                  $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove"))
                {
                    args.AddPassArg("obj");
                    args.Add("keys: keys.ToHashSet()");
                }
            }
            fg.AppendLine();

            if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No)
            {
                return;
            }
            fg.AppendLine("[DebuggerStepThrough]");
            using (var args = new FunctionWrapper(fg,
                                                  $"public static void Remove{obj.GetGenericTypes(MaskType.Normal)}"))
            {
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics));
                args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj");
                args.Add($"HashSet<{nameof(FormKey)}> keys");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new ArgsWrapper(fg,
                                                  $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove"))
                {
                    args.AddPassArg("obj");
                    args.AddPassArg("keys");
                }
            }
            fg.AppendLine();

            fg.AppendLine("[DebuggerStepThrough]");
            using (var args = new FunctionWrapper(fg,
                                                  $"public static void Remove{obj.GetGenericTypes(MaskType.Normal)}"))
            {
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics));
                args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj");
                args.Add($"{nameof(FormKey)} key");
                args.Add($"{nameof(Type)} type");
                args.Add($"bool throwIfUnknown = true");
            }
            using (new BraceWrapper(fg))
            {
                fg.AppendLine($"var keys = new HashSet<{nameof(FormKey)}>();");
                fg.AppendLine("keys.Add(key);");
                using (var args = new ArgsWrapper(fg,
                                                  $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove"))
                {
                    args.AddPassArg("obj");
                    args.AddPassArg("keys");
                    args.AddPassArg("type");
                    args.AddPassArg("throwIfUnknown");
                }
            }
            fg.AppendLine();

            if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No)
            {
                return;
            }
            fg.AppendLine("[DebuggerStepThrough]");
            using (var args = new FunctionWrapper(fg,
                                                  $"public static void Remove{obj.GetGenericTypes(MaskType.Normal)}"))
            {
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics));
                args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj");
                args.Add($"IEnumerable<{nameof(FormKey)}> keys");
                args.Add($"{nameof(Type)} type");
                args.Add($"bool throwIfUnknown = true");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new ArgsWrapper(fg,
                                                  $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove"))
                {
                    args.AddPassArg("obj");
                    args.Add("keys: keys.ToHashSet()");
                    args.AddPassArg("type");
                    args.AddPassArg("throwIfUnknown");
                }
            }
            fg.AppendLine();

            if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No)
            {
                return;
            }
            fg.AppendLine("[DebuggerStepThrough]");
            using (var args = new FunctionWrapper(fg,
                                                  $"public static void Remove{obj.GetGenericTypes(MaskType.Normal)}"))
            {
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics));
                args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj");
                args.Add($"HashSet<{nameof(FormKey)}> keys");
                args.Add($"{nameof(Type)} type");
                args.Add($"bool throwIfUnknown = true");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new ArgsWrapper(fg,
                                                  $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove"))
                {
                    args.AddPassArg("obj");
                    args.AddPassArg("keys");
                    args.AddPassArg("type");
                    args.AddPassArg("throwIfUnknown");
                }
            }
            fg.AppendLine();

            fg.AppendLine("[DebuggerStepThrough]");
            using (var args = new FunctionWrapper(fg,
                                                  $"public static void Remove{obj.GetGenericTypes(MaskType.Normal, "TMajor")}"))
            {
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics));
                args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj");
                args.Add($"TMajor record");
                args.Add($"bool throwIfUnknown = true");
                args.Wheres.Add($"where TMajor : {nameof(IMajorRecordGetter)}");
            }
            using (new BraceWrapper(fg))
            {
                fg.AppendLine($"var keys = new HashSet<{nameof(FormKey)}>();");
                fg.AppendLine("keys.Add(record.FormKey);");
                using (var args = new ArgsWrapper(fg,
                                                  $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove"))
                {
                    args.AddPassArg("obj");
                    args.AddPassArg("keys");
                    args.Add("type: typeof(TMajor)");
                    args.AddPassArg("throwIfUnknown");
                }
            }
            fg.AppendLine();

            if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No)
            {
                return;
            }
            fg.AppendLine("[DebuggerStepThrough]");
            using (var args = new FunctionWrapper(fg,
                                                  $"public static void Remove{obj.GetGenericTypes(MaskType.Normal, "TMajor")}"))
            {
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics));
                args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj");
                args.Add($"IEnumerable<TMajor> records");
                args.Add($"bool throwIfUnknown = true");
                args.Wheres.Add($"where TMajor : {nameof(IMajorRecordGetter)}");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new ArgsWrapper(fg,
                                                  $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove"))
                {
                    args.AddPassArg("obj");
                    args.Add("keys: records.Select(m => m.FormKey).ToHashSet()");
                    args.Add("type: typeof(TMajor)");
                    args.AddPassArg("throwIfUnknown");
                }
            }
            fg.AppendLine();

            fg.AppendLine("[DebuggerStepThrough]");
            using (var args = new FunctionWrapper(fg,
                                                  $"public static void Remove{obj.GetGenericTypes(MaskType.Normal, "TMajor")}"))
            {
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics));
                args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj");
                args.Add($"{nameof(FormKey)} key");
                args.Add($"bool throwIfUnknown = true");
                args.Wheres.Add($"where TMajor : {nameof(IMajorRecordGetter)}");
            }
            using (new BraceWrapper(fg))
            {
                fg.AppendLine($"var keys = new HashSet<{nameof(FormKey)}>();");
                fg.AppendLine("keys.Add(key);");
                using (var args = new ArgsWrapper(fg,
                                                  $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove"))
                {
                    args.AddPassArg("obj");
                    args.AddPassArg("keys");
                    args.Add("type: typeof(TMajor)");
                    args.AddPassArg("throwIfUnknown");
                }
            }
            fg.AppendLine();

            if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No)
            {
                return;
            }
            fg.AppendLine("[DebuggerStepThrough]");
            using (var args = new FunctionWrapper(fg,
                                                  $"public static void Remove{obj.GetGenericTypes(MaskType.Normal, "TMajor")}"))
            {
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics));
                args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj");
                args.Add($"IEnumerable<{nameof(FormKey)}> keys");
                args.Add($"bool throwIfUnknown = true");
                args.Wheres.Add($"where TMajor : {nameof(IMajorRecordGetter)}");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new ArgsWrapper(fg,
                                                  $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove"))
                {
                    args.AddPassArg("obj");
                    args.Add("keys: keys.ToHashSet()");
                    args.Add("type: typeof(TMajor)");
                    args.AddPassArg("throwIfUnknown");
                }
            }
            fg.AppendLine();

            if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No)
            {
                return;
            }
            fg.AppendLine("[DebuggerStepThrough]");
            using (var args = new FunctionWrapper(fg,
                                                  $"public static void Remove{obj.GetGenericTypes(MaskType.Normal, "TMajor")}"))
            {
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics));
                args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj");
                args.Add($"HashSet<{nameof(FormKey)}> keys");
                args.Add($"bool throwIfUnknown = true");
                args.Wheres.Add($"where TMajor : {nameof(IMajorRecordGetter)}");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new ArgsWrapper(fg,
                                                  $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove"))
                {
                    args.AddPassArg("obj");
                    args.AddPassArg("keys");
                    args.Add("type: typeof(TMajor)");
                    args.AddPassArg("throwIfUnknown");
                }
            }
            fg.AppendLine();
        }
Ejemplo n.º 24
0
        public override async Task GenerateInCommon(ObjectGeneration obj, FileGeneration fg, MaskTypeSet maskTypes)
        {
            bool getter = maskTypes.Applicable(LoquiInterfaceType.IGetter, CommonGenerics.Class);

            if (!getter)
            {
                return;
            }
            var accessor = new Accessor("obj");

            if (obj.Abstract)
            {
                return;
            }
            if (obj.GetObjectType() == ObjectType.Group)
            {
                return;
            }
            if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No)
            {
                return;
            }
            var overrideStr = await obj.FunctionOverride(async c => await MajorRecordModule.HasMajorRecords(c, includeBaseClass : false, includeSelf : true) != Case.No);

            using (var args = new FunctionWrapper(fg,
                                                  $"public{overrideStr}IEnumerable<IModContext<{obj.GetObjectData().GameCategory.Value.ModInterface(getter: false)}, IMajorRecordCommon, IMajorRecordCommonGetter>> EnumerateMajorRecordContexts"))
            {
                args.Add($"{obj.Interface(getter: getter, internalInterface: true)} obj");
                args.Add($"{nameof(ILinkCache)} linkCache");
                args.Add($"Type type");
                if (obj.GetObjectType() != ObjectType.Mod)
                {
                    args.Add($"{nameof(ModKey)} modKey");
                    args.Add($"IModContext? parent");
                }
                args.Add($"bool throwIfUnknown");
                if (obj.GetObjectType() == ObjectType.Record)
                {
                    args.Add($"Func<{obj.GetObjectData().GameCategory.Value.ModInterface(getter: false)}, {obj.Interface(getter: true)}, {obj.Interface(getter: false)}> getter");
                }
            }
            using (new BraceWrapper(fg))
            {
                if (obj.GetObjectType() == ObjectType.Record)
                {
                    using (var args = new ArgsWrapper(fg,
                                                      $"var curContext = new ModContext<{obj.GetObjectData().GameCategory.Value.ModInterface(getter: false)}, {obj.Interface(getter: false)}, {obj.Interface(getter: true)}>"))
                    {
                        args.Add($"{(obj.GetObjectType() == ObjectType.Mod ? "obj.ModKey" : "modKey")}");
                        args.Add("record: obj");
                        args.AddPassArg("getter");
                        args.AddPassArg("parent");
                    }
                }
                var fgCount = fg.Count;
                fg.AppendLine("switch (type.Name)");
                using (new BraceWrapper(fg))
                {
                    var gameCategory = obj.GetObjectData().GameCategory;
                    Dictionary <object, FileGeneration> generationDict = new Dictionary <object, FileGeneration>();
                    foreach (var field in obj.IterateFields())
                    {
                        FileGeneration fieldGen;
                        if (field is LoquiType loqui)
                        {
                            if (loqui.TargetObjectGeneration.IsListGroup())
                            {
                                continue;
                            }
                            var isMajorRecord = loqui.TargetObjectGeneration != null && await loqui.TargetObjectGeneration.IsMajorRecord();

                            if (!isMajorRecord &&
                                await MajorRecordModule.HasMajorRecords(loqui, includeBaseClass: true) == Case.No)
                            {
                                continue;
                            }

                            if (loqui.TargetObjectGeneration.GetObjectType() == ObjectType.Group)
                            {
                                fieldGen = generationDict.GetOrAdd(loqui.GetGroupTarget());
                            }
                            else
                            {
                                fieldGen = generationDict.GetOrAdd(((object)loqui?.TargetObjectGeneration) ?? loqui);
                            }
                        }
                        else if (field is ContainerType cont)
                        {
                            if (!(cont.SubTypeGeneration is LoquiType contLoqui))
                            {
                                continue;
                            }
                            if (contLoqui.RefType == LoquiType.LoquiRefType.Generic)
                            {
                                fieldGen = generationDict.GetOrAdd("default:");
                            }
                            else
                            {
                                fieldGen = generationDict.GetOrAdd(((object)contLoqui?.TargetObjectGeneration) ?? contLoqui);
                            }
                        }
                        else if (field is DictType dict)
                        {
                            if (dict.Mode != DictMode.KeyedValue)
                            {
                                continue;
                            }
                            if (!(dict.ValueTypeGen is LoquiType dictLoqui))
                            {
                                continue;
                            }
                            if (dictLoqui.RefType == LoquiType.LoquiRefType.Generic)
                            {
                                fieldGen = generationDict.GetOrAdd("default:");
                            }
                            else
                            {
                                fieldGen = generationDict.GetOrAdd(((object)dictLoqui?.TargetObjectGeneration) ?? dictLoqui);
                            }
                        }
                        else
                        {
                            continue;
                        }
                        await ApplyIterationLines(obj, field, fieldGen, accessor, getter);
                    }

                    bool doAdditionlDeepLogic = obj.Name != "ListGroup";

                    if (doAdditionlDeepLogic)
                    {
                        var deepRecordMapping = await MajorRecordModule.FindDeepRecords(obj);

                        foreach (var deepRec in deepRecordMapping)
                        {
                            FileGeneration deepFg = generationDict.GetOrAdd(deepRec.Key);
                            foreach (var field in deepRec.Value)
                            {
                                await ApplyIterationLines(obj, field, deepFg, accessor, getter, hasTarget : true, includeSelf : false);
                            }
                        }

                        HashSet <string> blackList = new HashSet <string>();
                        foreach (var kv in generationDict)
                        {
                            switch (kv.Key)
                            {
                            case LoquiType loqui:
                                if (loqui.RefType == LoquiType.LoquiRefType.Generic)
                                {
                                    // Handled in default case
                                    continue;
                                }
                                else
                                {
                                    fg.AppendLine($"case \"{loqui.Interface(getter: true)}\":");
                                    fg.AppendLine($"case \"{loqui.Interface(getter: false)}\":");
                                    if (loqui.HasInternalGetInterface)
                                    {
                                        fg.AppendLine($"case \"{loqui.Interface(getter: true, internalInterface: true)}\":");
                                    }
                                    if (loqui.HasInternalSetInterface)
                                    {
                                        fg.AppendLine($"case \"{loqui.Interface(getter: false, internalInterface: true)}\":");
                                    }
                                    if (loqui.RefType == LoquiType.LoquiRefType.Interface)
                                    {
                                        blackList.Add(loqui.SetterInterface);
                                    }
                                }
                                break;

                            case ObjectGeneration targetObj:
                                fg.AppendLine($"case \"{targetObj.ObjectName}\":");
                                fg.AppendLine($"case \"{targetObj.Interface(getter: true)}\":");
                                fg.AppendLine($"case \"{targetObj.Interface(getter: false)}\":");
                                if (targetObj.HasInternalGetInterface)
                                {
                                    fg.AppendLine($"case \"{targetObj.Interface(getter: true, internalInterface: true)}\":");
                                }
                                if (targetObj.HasInternalSetInterface)
                                {
                                    fg.AppendLine($"case \"{targetObj.Interface(getter: false, internalInterface: true)}\":");
                                }
                                break;

                            case string str:
                                if (str != "default:")
                                {
                                    throw new NotImplementedException();
                                }
                                continue;

                            default:
                                throw new NotImplementedException();
                            }
                            using (new DepthWrapper(fg))
                            {
                                fg.AppendLines(kv.Value);
                                fg.AppendLine("yield break;");
                            }
                        }

                        // Generate for major record marker interfaces
                        if (LinkInterfaceModule.ObjectMappings.TryGetValue(obj.ProtoGen.Protocol, out var interfs))
                        {
                            foreach (var interf in interfs)
                            {
                                if (blackList.Contains(interf.Key))
                                {
                                    continue;
                                }
                                FileGeneration             subFg         = new FileGeneration();
                                HashSet <ObjectGeneration> passedObjects = new HashSet <ObjectGeneration>();
                                HashSet <TypeGeneration>   deepObjects   = new HashSet <TypeGeneration>();
                                foreach (var subObj in interf.Value)
                                {
                                    var grup = obj.Fields
                                               .WhereCastable <TypeGeneration, GroupType>()
                                               .Where(g => g.GetGroupTarget() == subObj)
                                               .FirstOrDefault();

                                    if (grup != null)
                                    {
                                        subFg.AppendLine($"foreach (var item in EnumerateMajorRecordContexts({accessor}, linkCache, typeof({grup.GetGroupTarget().Interface(getter: true)}), throwIfUnknown: throwIfUnknown))");
                                        using (new BraceWrapper(subFg))
                                        {
                                            subFg.AppendLine("yield return item;");
                                        }
                                        passedObjects.Add(grup.GetGroupTarget());
                                    }
                                    else if (deepRecordMapping.TryGetValue(subObj, out var deepRec))
                                    {
                                        foreach (var field in deepRec)
                                        {
                                            deepObjects.Add(field);
                                        }
                                    }
                                }
                                foreach (var deepObj in deepObjects)
                                {
                                    await ApplyIterationLines(obj, deepObj, subFg, accessor, getter, blackList : passedObjects, hasTarget : true, includeSelf : false);
                                }
                                if (!subFg.Empty)
                                {
                                    fg.AppendLine($"case \"{interf.Key}\":");
                                    fg.AppendLine($"case \"{interf.Key}Getter\":");
                                    using (new BraceWrapper(fg))
                                    {
                                        fg.AppendLines(subFg);
                                        fg.AppendLine("yield break;");
                                    }
                                }
                            }
                        }
                    }

                    fg.AppendLine("default:");
                    using (new DepthWrapper(fg))
                    {
                        if (generationDict.TryGetValue("default:", out var gen))
                        {
                            fg.AppendLines(gen);
                            fg.AppendLine("yield break;");
                        }
                        else
                        {
                            fg.AppendLine("if (throwIfUnknown)");
                            using (new BraceWrapper(fg))
                            {
                                fg.AppendLine("throw new ArgumentException($\"Unknown major record type: {type}\");");
                            }
                            fg.AppendLine($"else");
                            using (new BraceWrapper(fg))
                            {
                                fg.AppendLine("yield break;");
                            }
                        }
                    }
                }
            }
            fg.AppendLine();
        }
Ejemplo n.º 25
0
        public override async Task GenerateInCommonMixin(ObjectGeneration obj, FileGeneration fg)
        {
            if (obj.GetObjectType() != ObjectType.Mod)
            {
                return;
            }
            var    needsCatch = obj.GetObjectType() == ObjectType.Mod;
            string catchLine  = needsCatch ? ".Catch(e => throw RecordException.Factory(e, obj.ModKey))" : string.Empty;
            string enderSemi  = needsCatch ? string.Empty : ";";

            fg.AppendLine("[DebuggerStepThrough]");
            using (var args = new FunctionWrapper(fg,
                                                  $"public static IEnumerable<IModContext<{obj.GetObjectData().GameCategory.Value.ModInterface(getter: false)}, TSetter, TGetter>> EnumerateMajorRecordContexts{obj.GetGenericTypes(MaskType.Normal, new string[] { "TSetter", "TGetter" })}"))
            {
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.IGetter, obj.Generics));
                args.Wheres.Add($"where TSetter : class, IMajorRecordCommon, TGetter");
                args.Wheres.Add($"where TGetter : class, IMajorRecordCommonGetter");
                args.Add($"this {obj.Interface(getter: true, internalInterface: true)} obj");
                args.Add($"{nameof(ILinkCache)} linkCache");
                args.Add($"bool throwIfUnknown = true");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new FunctionWrapper(fg,
                                                      $"return {obj.CommonClassInstance("obj", LoquiInterfaceType.IGetter, CommonGenerics.Class)}.EnumerateMajorRecordContexts"))
                {
                    args.AddPassArg("obj");
                    args.AddPassArg("linkCache");
                    args.Add("type: typeof(TGetter)");
                    args.AddPassArg("throwIfUnknown");
                }
                using (new DepthWrapper(fg))
                {
                    fg.AppendLine($".Select(m => m.AsType<{obj.GetObjectData().GameCategory.Value.ModInterface(getter: false)}, {nameof(IMajorRecordCommon)}, {nameof(IMajorRecordCommonGetter)}, TSetter, TGetter>()){enderSemi}");
                    if (needsCatch)
                    {
                        fg.AppendLine($"{catchLine};");
                    }
                }
            }
            fg.AppendLine();

            fg.AppendLine("[DebuggerStepThrough]");
            using (var args = new FunctionWrapper(fg,
                                                  $"public static IEnumerable<IModContext<{obj.GetObjectData().GameCategory.Value.ModInterface(getter: false)}, IMajorRecordCommon, IMajorRecordCommonGetter>> EnumerateMajorRecordContexts{obj.GetGenericTypes(MaskType.Normal)}"))
            {
                args.Add($"this {obj.Interface(getter: true, internalInterface: true)} obj");
                args.Add($"{nameof(ILinkCache)} linkCache");
                args.Add($"Type type");
                args.Add($"bool throwIfUnknown = true");
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.IGetter, obj.Generics));
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new ArgsWrapper(fg,
                                                  $"return {obj.CommonClassInstance("obj", LoquiInterfaceType.IGetter, CommonGenerics.Class)}.EnumerateMajorRecordContexts"))
                {
                    args.AddPassArg("obj");
                    args.AddPassArg("linkCache");
                    args.AddPassArg("type");
                    args.AddPassArg("throwIfUnknown");
                }
            }
            fg.AppendLine();
        }
Ejemplo n.º 26
0
        public override async Task GenerateInClass(ObjectGeneration obj, FileGeneration fg)
        {
            await base.GenerateInClass(obj, fg);

            if (!await obj.IsMajorRecord())
            {
                return;
            }
            using (var args = new FunctionWrapper(fg,
                                                  $"public {obj.Name}"))
            {
                args.Add($"{nameof(FormKey)} formKey");
                if (obj.GetObjectData().HasMultipleReleases)
                {
                    args.Add($"{obj.GetObjectData().GameCategory}Release gameRelease");
                }
            }
            using (new BraceWrapper(fg))
            {
                fg.AppendLine("this.FormKey = formKey;");
                if (obj.GetObjectData().HasMultipleReleases)
                {
                    fg.AppendLine("this.FormVersion = gameRelease.ToGameRelease().GetDefaultFormVersion()!.Value;");
                }
                fg.AppendLine("CustomCtor();");
            }
            fg.AppendLine();

            // Used for reflection based construction
            using (var args = new FunctionWrapper(fg,
                                                  $"private {obj.Name}"))
            {
                args.Add($"{nameof(FormKey)} formKey");
                args.Add($"{nameof(GameRelease)} gameRelease");
            }
            using (new BraceWrapper(fg))
            {
                fg.AppendLine("this.FormKey = formKey;");
                if (obj.GetObjectData().GameCategory?.HasFormVersion() ?? false)
                {
                    fg.AppendLine("this.FormVersion = gameRelease.GetDefaultFormVersion()!.Value;");
                }
                fg.AppendLine("CustomCtor();");
            }
            fg.AppendLine();

            if (obj.GetObjectData().GameCategory?.HasFormVersion() ?? false)
            {
                using (var args = new FunctionWrapper(fg,
                                                      $"internal {obj.Name}"))
                {
                    args.Add($"{nameof(FormKey)} formKey");
                    args.Add($"ushort formVersion");
                }
                using (new BraceWrapper(fg))
                {
                    fg.AppendLine("this.FormKey = formKey;");
                    fg.AppendLine("this.FormVersion = formVersion;");
                    fg.AppendLine("CustomCtor();");
                }
                fg.AppendLine();
            }

            fg.AppendLine($"public {obj.Name}(I{obj.GetObjectData().GameCategory}Mod mod)");
            using (new DepthWrapper(fg))
            {
                using (var args = new FunctionWrapper(fg, ": this"))
                {
                    args.Add($"mod.{nameof(IMod.GetNextFormKey)}()");
                    if (obj.GetObjectData().HasMultipleReleases)
                    {
                        args.Add($"mod.{obj.GetObjectData().GameCategory}Release");
                    }
                }
            }
            using (new BraceWrapper(fg))
            {
            }
            fg.AppendLine();

            fg.AppendLine($"public {obj.Name}(I{obj.GetObjectData().GameCategory}Mod mod, string editorID)");
            using (new DepthWrapper(fg))
            {
                using (var args = new FunctionWrapper(fg, ": this"))
                {
                    args.Add($"mod.{nameof(IMod.GetNextFormKey)}(editorID)");
                    if (obj.GetObjectData().HasMultipleReleases)
                    {
                        args.Add($"mod.{obj.GetObjectData().GameCategory}Release");
                    }
                }
            }
            using (new BraceWrapper(fg))
            {
                fg.AppendLine("this.EditorID = editorID;");
            }
            fg.AppendLine();
        }
Ejemplo n.º 27
0
        private void GenerateWriteParallel(ObjectGeneration obj, FileGeneration fg)
        {
            LoquiType groupInstance     = null;
            LoquiType listGroupInstance = null;
            var       objData           = obj.GetObjectData();

            fg.AppendLine("const int CutCount = 100;");
            using (var args = new FunctionWrapper(fg,
                                                  "public static void WriteParallel"))
            {
                args.Add($"{obj.Interface(getter: true, internalInterface: false)} item");
                args.Add($"Stream stream");
                args.Add($"{nameof(BinaryWriteParameters)} param");
                args.Add($"ModKey modKey");
            }
            using (new BraceWrapper(fg))
            {
                string gameConstantsStr;
                if (objData.GameReleaseOptions == null)
                {
                    gameConstantsStr = $"{nameof(GameConstants)}.{obj.GetObjectData().GameCategory}";
                }
                else
                {
                    fg.AppendLine($"var gameConstants = {nameof(GameConstants)}.Get(item.{ReleaseEnumName(obj)}.ToGameRelease());");
                    gameConstantsStr = $"gameConstants";
                }
                fg.AppendLine($"var bundle = new {nameof(WritingBundle)}({gameConstantsStr});");
                fg.AppendLine($"var writer = new MutagenWriter(stream, bundle);");
                using (var args = new ArgsWrapper(fg,
                                                  $"{nameof(ModHeaderWriteLogic)}.{nameof(ModHeaderWriteLogic.WriteHeader)}"))
                {
                    args.AddPassArg("param");
                    args.AddPassArg("writer");
                    args.Add("mod: item");
                    args.Add("modHeader: item.ModHeader.DeepCopy()");
                    args.AddPassArg("modKey");
                }

                int groupCount = obj.IterateFields()
                                 .Select(f => f as LoquiType)
                                 .Where(l => l != null)
                                 .Where(l => l.TargetObjectGeneration?.GetObjectData().ObjectType == ObjectType.Group)
                                 .Count();

                fg.AppendLine($"Stream[] outputStreams = new Stream[{groupCount}];");
                fg.AppendLine($"List<Action> toDo = new List<Action>();");
                int i = 0;
                foreach (var field in obj.IterateFields())
                {
                    if (!(field is LoquiType loqui))
                    {
                        continue;
                    }
                    if (loqui.TargetObjectGeneration?.GetObjectData().ObjectType != ObjectType.Group)
                    {
                        continue;
                    }
                    if (loqui.TargetObjectGeneration.Name == "ListGroup")
                    {
                        listGroupInstance = loqui;
                    }
                    else
                    {
                        groupInstance = loqui;
                    }
                    if (loqui.GetGroupTarget().GetObjectData().CustomBinaryEnd == CustomEnd.Off &&
                        loqui.TargetObjectGeneration.Name != "ListGroup")
                    {
                        fg.AppendLine($"toDo.Add(() => WriteGroupParallel(item.{field.Name}, writer.MetaData.MasterReferences!, {i}{(objData.GameReleaseOptions == null ? null : ", gameConstants")}, outputStreams{(objData.UsesStringFiles ? ", param.StringsWriter" : null)}));");
                    }
                    else
                    {
                        fg.AppendLine($"toDo.Add(() => Write{field.Name}Parallel(item.{field.Name}, writer.MetaData.MasterReferences!, {i}{(objData.GameReleaseOptions == null ? null : ", gameConstants")}, outputStreams));");
                    }
                    i++;
                }
                fg.AppendLine("Parallel.Invoke(toDo.ToArray());");
                using (var args = new ArgsWrapper(fg,
                                                  $"{nameof(UtilityTranslation)}.{nameof(UtilityTranslation.CompileStreamsInto)}"))
                {
                    args.Add("outputStreams.NotNull()");
                    args.Add("stream");
                }
            }
            fg.AppendLine();

            if (groupInstance != null)
            {
                using (var args = new FunctionWrapper(fg,
                                                      $"public static void WriteGroupParallel<T>"))
                {
                    args.Add("IGroupGetter<T> group");
                    args.Add($"{nameof(MasterReferenceReader)} masters");
                    args.Add("int targetIndex");
                    if (objData.GameReleaseOptions != null)
                    {
                        args.Add($"{nameof(GameConstants)} gameConstants");
                    }
                    args.Add("Stream[] streamDepositArray");
                    if (objData.UsesStringFiles)
                    {
                        args.Add($"{nameof(StringsWriter)}? stringsWriter");
                    }
                    args.Wheres.AddRange(groupInstance.TargetObjectGeneration.GenerateWhereClauses(LoquiInterfaceType.IGetter, groupInstance.TargetObjectGeneration.Generics));
                }
                using (new BraceWrapper(fg))
                {
                    string gameConstantsStr;
                    if (objData.GameReleaseOptions == null)
                    {
                        gameConstantsStr = $"{nameof(GameConstants)}.{obj.GetObjectData().GameCategory}";
                    }
                    else
                    {
                        gameConstantsStr = "gameConstants";
                    }
                    fg.AppendLine("if (group.RecordCache.Count == 0) return;");
                    fg.AppendLine($"var cuts = group.Cut(CutCount).ToArray();");
                    fg.AppendLine($"Stream[] subStreams = new Stream[cuts.Length + 1];");
                    fg.AppendLine($"byte[] groupBytes = new byte[{gameConstantsStr}.GroupConstants.HeaderLength];");
                    fg.AppendLine($"BinaryPrimitives.WriteInt32LittleEndian(groupBytes.AsSpan(), RecordTypes.GRUP.TypeInt);");
                    fg.AppendLine($"var groupByteStream = new MemoryStream(groupBytes);");
                    fg.AppendLine($"using (var stream = new MutagenWriter(groupByteStream, {gameConstantsStr}, dispose: false))");
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine($"stream.Position += 8;");
                        fg.AppendLine($"GroupBinaryWriteTranslation.WriteEmbedded<T>(group, stream);");
                    }
                    fg.AppendLine($"subStreams[0] = groupByteStream;");
                    fg.AppendLine($"Parallel.ForEach(cuts, (cutItems, state, counter) =>");
                    using (new BraceWrapper(fg)
                    {
                        AppendSemicolon = true, AppendParenthesis = true
                    })
                    {
                        fg.AppendLine($"{nameof(MemoryTributary)} trib = new {nameof(MemoryTributary)}();");
                        fg.AppendLine($"var bundle = new {nameof(WritingBundle)}({gameConstantsStr})");
                        using (var prop = new PropertyCtorWrapper(fg))
                        {
                            prop.Add($"{nameof(WritingBundle.MasterReferences)} = masters");
                            if (objData.UsesStringFiles)
                            {
                                prop.Add($"{nameof(WritingBundle.StringsWriter)} = stringsWriter");
                            }
                        }
                        fg.AppendLine($"using (var stream = new MutagenWriter(trib, bundle, dispose: false))");
                        using (new BraceWrapper(fg))
                        {
                            fg.AppendLine($"foreach (var item in cutItems)");
                            using (new BraceWrapper(fg))
                            {
                                fg.AppendLine($"item.WriteToBinary(stream);");
                            }
                        }
                        fg.AppendLine($"subStreams[(int)counter + 1] = trib;");
                    }
                    fg.AppendLine($"UtilityTranslation.CompileSetGroupLength(subStreams, groupBytes);");
                    fg.AppendLine($"streamDepositArray[targetIndex] = new CompositeReadStream(subStreams, resetPositions: true);");
                }
                fg.AppendLine();
            }
        }
Ejemplo n.º 28
0
        public override void GenerateWriteToNode(ObjectGeneration obj, FileGeneration fg)
        {
            using (var args = new FunctionWrapper(fg,
                                                  $"public static void WriteToNode{ModuleNickname}{obj.GetGenericTypes(MaskType.Normal)}"))
            {
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.IGetter, defs: obj.Generics));
                args.Add($"{obj.Interface(internalInterface: true, getter: true)} item");
                args.Add($"XElement {XmlTranslationModule.XElementLine.GetParameterName(obj)}");
                args.Add($"ErrorMaskBuilder? errorMask");
                args.Add($"{nameof(TranslationCrystal)}? translationMask");
            }
            using (new BraceWrapper(fg))
            {
                if (obj.HasLoquiBaseObject)
                {
                    using (var args = new ArgsWrapper(fg,
                                                      $"{this.TranslationWriteClass(obj.BaseClass)}.WriteToNode{ModuleNickname}"))
                    {
                        args.Add($"item: item");
                        args.Add($"{XmlTranslationModule.XElementLine.GetParameterName(obj)}: {XmlTranslationModule.XElementLine.GetParameterName(obj)}");
                        args.Add($"errorMask: errorMask");
                        args.Add($"translationMask: translationMask");
                    }
                }

                void generateNormal(XmlTranslationGeneration generator, TypeGeneration field)
                {
                    if (!generator.ShouldGenerateWrite(field))
                    {
                        return;
                    }

                    List <string> conditions = new List <string>();

                    if (field.HasBeenSet)
                    {
                        conditions.Add($"{field.HasBeenSetAccessor(getter: true, accessor: Accessor.FromType(field, "item"))}");
                    }
                    if (this.TranslationMaskParameter)
                    {
                        conditions.Add(field.GetTranslationIfAccessor("translationMask"));
                    }
                    if (conditions.Count > 0)
                    {
                        using (var args = new IfWrapper(fg, ANDs: true))
                        {
                            foreach (var item in conditions)
                            {
                                args.Add(item);
                            }
                        }
                    }
                    using (new BraceWrapper(fg, doIt: conditions.Count > 0))
                    {
                        var maskType = this.Gen.MaskModule.GetMaskModule(field.GetType()).GetErrorMaskTypeStr(field);
                        generator.GenerateWrite(
                            fg: fg,
                            objGen: obj,
                            typeGen: field,
                            writerAccessor: $"{XmlTranslationModule.XElementLine.GetParameterName(obj)}",
                            itemAccessor: Accessor.FromType(field, "item"),
                            errorMaskAccessor: $"errorMask",
                            translationMaskAccessor: "translationMask",
                            nameAccessor: $"nameof(item.{field.Name})");
                    }
                }

                foreach (var field in obj.IterateFields(expandSets: SetMarkerType.ExpandSets.FalseAndInclude, nonIntegrated: true))
                {
                    if (!this.TryGetTypeGeneration(field.GetType(), out var generator))
                    {
                        if (!field.IntegrateField)
                        {
                            continue;
                        }
                        throw new ArgumentException("Unsupported type generator: " + field);
                    }

                    if (field is DataType dataType)
                    {
                        if (dataType.HasBeenSet)
                        {
                            fg.AppendLine($"if (item.{dataType.StateName}.HasFlag({obj.Name}.{dataType.EnumName}.Has))");
                        }
                        using (new BraceWrapper(fg, doIt: dataType.HasBeenSet))
                        {
                            bool isInRange             = false;
                            int  encounteredBreakIndex = 0;
                            foreach (var subField in dataType.IterateFieldsWithMeta())
                            {
                                if (!this.TryGetTypeGeneration(subField.Field.GetType(), out var subGenerator))
                                {
                                    throw new ArgumentException("Unsupported type generator: " + subField.Field);
                                }

                                var subData = subField.Field.GetFieldData();
                                if (!subGenerator.ShouldGenerateCopyIn(subField.Field))
                                {
                                    continue;
                                }
                                if (subField.BreakIndex != -1)
                                {
                                    fg.AppendLine($"if (!item.{dataType.StateName}.HasFlag({obj.Name}.{dataType.EnumName}.Break{subField.BreakIndex}))");
                                    fg.AppendLine("{");
                                    fg.Depth++;
                                    encounteredBreakIndex++;
                                }
                                if (subField.Range != null && !isInRange)
                                {
                                    isInRange = true;
                                    fg.AppendLine($"if (item.{dataType.StateName}.HasFlag({obj.Name}.{dataType.EnumName}.Range{subField.RangeIndex}))");
                                    fg.AppendLine("{");
                                    fg.Depth++;
                                }
                                if (subField.Range == null && isInRange)
                                {
                                    isInRange = false;
                                    fg.Depth--;
                                    fg.AppendLine("}");
                                }
                                generateNormal(subGenerator, subField.Field);
                            }
                            for (int i = 0; i < encounteredBreakIndex; i++)
                            {
                                fg.Depth--;
                                fg.AppendLine("}");
                                if (i == encounteredBreakIndex - 1)
                                {
                                    fg.AppendLine("else");
                                    using (new BraceWrapper(fg))
                                    {
                                        fg.AppendLine($"node.Add(new XElement(\"Has{dataType.EnumName}\"));");
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        generateNormal(generator, field);
                    }
                }
            }
            fg.AppendLine();
        }
Ejemplo n.º 29
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);
        }
        public void Execute(GeneratorExecutionContext context)
        {
            if (context.CancellationToken.IsCancellationRequested)
            {
                return;
            }
            if (context.SyntaxReceiver is not CustomAspectInterfaceReceiver customAspectReceiver)
            {
                return;
            }

            try
            {
                if (context.CancellationToken.IsCancellationRequested)
                {
                    return;
                }
                var interfaceSymbols = GetInterfaceTypeDictionary(context, customAspectReceiver);

                // Group things by namespace
                if (context.CancellationToken.IsCancellationRequested)
                {
                    return;
                }
                var targets = new Dictionary <string, GenerationTarget>();

                foreach (var namespaceGroup in interfaceSymbols.Values
                         .GroupBy(x => x.Symbol.ContainingNamespace))
                {
                    targets[namespaceGroup.Key.Name] = new GenerationTarget(
                        namespaceGroup.Key.Name,
                        namespaceGroup,
                        new());
                }

                HashSet <string> requiredUsings = new(targets.SelectMany(x => x.Value.UsedInterfaces)
                                                      .SelectMany(x => x.Types)
                                                      .Select(i => i.Symbol)
                                                      .NotNull()
                                                      .Select(x => x.ContainingNamespace.ToString()));

                // Generate
                foreach (var namespaceGroup in targets)
                {
                    if (context.CancellationToken.IsCancellationRequested)
                    {
                        return;
                    }
                    var fg = new FileGeneration();

                    foreach (var use in requiredUsings)
                    {
                        fg.AppendLine($"using {use};");
                    }
                    fg.AppendLine();

                    using (new NamespaceWrapper(fg, namespaceGroup.Key))
                    {
                        using (new RegionWrapper(fg, "Wrappers"))
                        {
                            foreach (var decl in namespaceGroup.Value.UsedInterfaces)
                            {
                                if (context.CancellationToken.IsCancellationRequested)
                                {
                                    return;
                                }
                                foreach (var t in decl.Types)
                                {
                                    var className = $"{t.Syntax.Type}Wrapper";
                                    using (var c = new ClassWrapper(fg, className))
                                    {
                                        c.Interfaces.Add(decl.Symbol.Name);
                                    }
                                    using (new BraceWrapper(fg))
                                    {
                                        fg.AppendLine($"private readonly {t.Syntax.Type} _wrapped;");
                                        foreach (var member in decl.Symbol.GetMembers())
                                        {
                                            switch (member)
                                            {
                                            case IPropertySymbol prop:
                                                fg.AppendLine($"public {prop.Type} {prop.Name}");
                                                using (new BraceWrapper(fg))
                                                {
                                                    if (!prop.IsWriteOnly)
                                                    {
                                                        fg.AppendLine($"get => _wrapped.{member.Name};");
                                                    }
                                                    if (!prop.IsReadOnly)
                                                    {
                                                        fg.AppendLine($"set => _wrapped.{member.Name} = value;");
                                                    }
                                                }
                                                break;

                                            default:
                                                continue;
                                            }
                                            fg.AppendLine();
                                        }

                                        using (var args = new FunctionWrapper(fg, $"public {className}"))
                                        {
                                            args.Add($"{t.Syntax.Type} rhs");
                                        }
                                        using (new BraceWrapper(fg))
                                        {
                                            fg.AppendLine("_wrapped = rhs;");
                                        }
                                    }
                                    fg.AppendLine();
                                }
                            }
                            fg.AppendLine();
                        }

                        if (context.CancellationToken.IsCancellationRequested)
                        {
                            return;
                        }
                        using (new RegionWrapper(fg, "Mix Ins"))
                        {
                            using (var c = new ClassWrapper(fg, "WrapperMixIns"))
                            {
                                c.Static = true;
                            }
                            using (new BraceWrapper(fg))
                            {
                                foreach (var decl in namespaceGroup.Value.UsedInterfaces)
                                {
                                    if (context.CancellationToken.IsCancellationRequested)
                                    {
                                        return;
                                    }
                                    foreach (var t in decl.Types)
                                    {
                                        using (var args = new FunctionWrapper(fg,
                                                                              $"public static {t.Syntax.Type}Wrapper As{decl.Symbol.Name}"))
                                        {
                                            args.Add($"this {t.Syntax.Type} rhs");
                                        }
                                        using (new BraceWrapper(fg))
                                        {
                                            fg.AppendLine($"return new {t.Syntax.Type}Wrapper(rhs);");
                                        }
                                        fg.AppendLine();
                                    }
                                }
                            }
                        }
                    }
                    context.AddSource($"CustomAspectInterfaces.g.cs", fg.ToString());
                }
            }
            catch (Exception ex)
            {
                customAspectReceiver.Exceptions.Add(ex);
            }

            if (customAspectReceiver.Exceptions.Count > 0)
            {
                context.AddSource($"Errors.g.cs", $"Number of exceptions: {customAspectReceiver.Exceptions.Count}\n" +
                                  $"{customAspectReceiver.Exceptions.FirstOrDefault()}");
            }
        }