Beispiel #1
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($"IGroupGetter<T> {nameof(IModGetter)}.{nameof(IModGetter.GetTopLevelGroup)}<T>() => this.{nameof(IModGetter.GetTopLevelGroup)}<T>();");
            fg.AppendLine($"IGroupGetter {nameof(IModGetter)}.{nameof(IModGetter.GetTopLevelGroup)}(Type type) => this.{nameof(IModGetter.GetTopLevelGroup)}(type);");
            fg.AppendLine($"IGroup<T> {nameof(IMod)}.{nameof(IMod.GetTopLevelGroup)}<T>() => this.{nameof(IMod.GetTopLevelGroup)}<T>();");
            fg.AppendLine($"IGroup {nameof(IMod)}.{nameof(IMod.GetTopLevelGroup)}(Type type) => this.{nameof(IMod.GetTopLevelGroup)}(type);");
            fg.AppendLine($"void IModGetter.WriteToBinary({nameof(FilePath)} path, {nameof(BinaryWriteParameters)}? param, IFileSystem? fileSystem) => this.WriteToBinary(path, importMask: null, param: param, fileSystem: fileSystem);");
            fg.AppendLine($"void IModGetter.WriteToBinaryParallel({nameof(FilePath)} path, {nameof(BinaryWriteParameters)}? param, IFileSystem? fileSystem, {nameof(ParallelWriteParameters)}? parallelWriteParams) => this.WriteToBinaryParallel(path, param, fileSystem: fileSystem, parallelParam: parallelWriteParams);");
            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 = 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 == $"{obj.ProtoGen.Protocol.Namespace}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 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.EndsWith("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);
        }
Beispiel #2
0
        private void GenerateWriteParallel(ObjectGeneration obj, FileGeneration fg)
        {
            LoquiType groupInstance     = null;
            LoquiType listGroupInstance = null;
            var       objData           = obj.GetObjectData();

            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($"{nameof(ParallelWriteParameters)} parallelParam");
                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})");
                using (new BraceWrapper(fg)
                {
                    AppendSemicolon = true
                })
                {
                    fg.AppendLine("StringsWriter = param.StringsWriter,");
                    fg.AppendLine("TargetLanguageOverride = param.TargetLanguageOverride,");
                }

                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.EndsWith("ListGroup"))
                    {
                        listGroupInstance = loqui;
                    }
                    else
                    {
                        groupInstance = loqui;
                    }
                    if (loqui.GetGroupTarget().GetObjectData().CustomBinaryEnd == CustomEnd.Off &&
                        !loqui.TargetObjectGeneration.Name.EndsWith("ListGroup"))
                    {
                        fg.AppendLine($"toDo.Add(() => WriteGroupParallel(item.{field.Name}, {i}, outputStreams, bundle, parallelParam));");
                    }
                    else
                    {
                        fg.AppendLine($"toDo.Add(() => Write{field.Name}Parallel(item.{field.Name}, {i}, outputStreams, bundle, parallelParam));");
                    }
                    i++;
                }
                fg.AppendLine("Parallel.Invoke(parallelParam.ParallelOptions, toDo.ToArray());");
                using (var args = new ArgsWrapper(fg,
                                                  $"{nameof(PluginUtilityTranslation)}.{nameof(PluginUtilityTranslation.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($"I{obj.ProtoGen.Protocol.Namespace}GroupGetter<T> group");
                    args.Add("int targetIndex");
                    args.Add("Stream[] streamDepositArray");
                    args.Add($"{nameof(WritingBundle)} bundle");
                    args.Add($"{nameof(ParallelWriteParameters)} parallelParam");
                    args.Wheres.AddRange(groupInstance.TargetObjectGeneration.GenerateWhereClauses(LoquiInterfaceType.IGetter, groupInstance.TargetObjectGeneration.Generics));
                }
                using (new BraceWrapper(fg))
                {
                    fg.AppendLine("if (group.RecordCache.Count == 0) return;");
                    fg.AppendLine($"var cuts = group.Cut(parallelParam.CutCount).ToArray();");
                    fg.AppendLine($"Stream[] subStreams = new Stream[cuts.Length + 1];");
                    fg.AppendLine($"byte[] groupBytes = new byte[bundle.Constants.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, bundle.Constants, dispose: false))");
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine($"stream.Position += 8;");
                        fg.AppendLine($"{obj.ProtoGen.Protocol.Namespace}GroupBinaryWriteTranslation.WriteEmbedded<T>(group, stream);");
                    }
                    fg.AppendLine($"subStreams[0] = groupByteStream;");
                    fg.AppendLine($"Parallel.ForEach(cuts, parallelParam.ParallelOptions, (cutItems, state, counter) =>");
                    using (new BraceWrapper(fg)
                    {
                        AppendSemicolon = true, AppendParenthesis = true
                    })
                    {
                        fg.AppendLine($"{nameof(MemoryTributary)} trib = new {nameof(MemoryTributary)}();");
                        fg.AppendLine($"using (var stream = new MutagenWriter(trib, bundle with {{}}, 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($"{nameof(PluginUtilityTranslation)}.CompileSetGroupLength(subStreams, groupBytes);");
                    fg.AppendLine($"streamDepositArray[targetIndex] = new CompositeReadStream(subStreams, resetPositions: true);");
                }
                fg.AppendLine();
            }
        }
Beispiel #3
0
        public override async Task GenerateInVoid(ObjectGeneration obj, FileGeneration fg)
        {
            if (obj.GetObjectType() != ObjectType.Mod)
            {
                return;
            }
            using (new NamespaceWrapper(fg, obj.Namespace, fileScoped: false))
            {
                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()");
                                }
                            }
                        }
                    }
                }
            }

            GenerateModGameCategoryRegistration(obj, fg);
        }
Beispiel #4
0
        public override async Task GenerateInCommonMixin(ObjectGeneration obj, FileGeneration fg)
        {
            await base.GenerateInCommonMixin(obj, fg);

            var    objData = obj.GetObjectData();
            string gameReleaseStr;

            if (objData.GameReleaseOptions == null)
            {
                gameReleaseStr = $"{nameof(GameRelease)}.{obj.GetObjectData().GameCategory}";
            }
            else
            {
                gameReleaseStr = $"item.GameRelease";
            }

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

            using (var args = new FunctionWrapper(fg,
                                                  $"public static IGroupGetter {nameof(IModGetter.GetTopLevelGroup)}"))
            {
                args.Add($"this {obj.Interface(getter: true)} obj");
                args.Add("Type type");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new ArgsWrapper(fg,
                                                  $"return (IGroupGetter){obj.CommonClassInstance("obj", LoquiInterfaceType.IGetter, CommonGenerics.Class, MaskType.Normal)}.GetGroup"))
                {
                    args.AddPassArg("obj");
                    args.AddPassArg("type");
                }
            }
            fg.AppendLine();

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

            using (var args = new FunctionWrapper(fg,
                                                  $"public static IGroup {nameof(IModGetter.GetTopLevelGroup)}"))
            {
                args.Add($"this {obj.Interface(getter: false)} obj");
                args.Add("Type type");
            }
            using (new BraceWrapper(fg))
            {
                using (var args = new ArgsWrapper(fg,
                                                  $"return (IGroup){obj.CommonClassInstance("obj", LoquiInterfaceType.IGetter, CommonGenerics.Class, MaskType.Normal)}.GetGroup"))
                {
                    args.AddPassArg("obj");
                    args.AddPassArg("type");
                }
            }
            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");
                args.Add($"{nameof(ParallelWriteParameters)}? parallelParam = 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($"parallelParam: parallelParam ?? {nameof(ParallelWriteParameters)}.{nameof(ParallelWriteParameters.Default)}");
                    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");
                args.Add($"{nameof(ParallelWriteParameters)}? parallelParam = null");
                args.Add($"{nameof(IFileSystem)}? fileSystem = null");
            }
            using (new BraceWrapper(fg))
            {
                fg.AppendLine($"param ??= {nameof(BinaryWriteParameters)}.{nameof(BinaryWriteParameters.Default)};");
                fg.AppendLine($"parallelParam ??= {nameof(ParallelWriteParameters)}.{nameof(ParallelWriteParameters.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($"param.StringsWriter ??= EnumExt.HasFlag((int)item.ModHeader.Flags, (int)ModHeaderCommonFlag.Localized) ? new StringsWriter({gameReleaseStr}, modKey, Path.Combine(Path.GetDirectoryName(path)!, \"Strings\"), {nameof(MutagenEncodingProvider)}.{nameof(MutagenEncodingProvider.Instance)}) : null;");
                    fg.AppendLine("bool disposeStrings = param.StringsWriter != null;");
                }
                fg.AppendLine("using (var stream = fileSystem.GetOrDefault().FileStream.Create(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.AddPassArg("parallelParam");
                        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();
        }
Beispiel #5
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))
            {
                fg.AppendLine($"var masterRefs = UtilityTranslation.ConstructWriteMasters(item, param);");
                fg.AppendLine($"var bundle = new {nameof(WritingBundle)}({nameof(GameConstants)}.{obj.GetObjectData().GameMode});");
                fg.AppendLine($"bundle.{nameof(WritingBundle.MasterReferences)} = masterRefs;");
                using (var args = new ArgsWrapper(fg,
                                                  $"{obj.ObjectName}BinaryWriteTranslation.WriteModHeader"))
                {
                    args.Add("item");
                    args.Add($"new MutagenWriter(stream, bundle)");
                    args.Add("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}, masterRefs, {i}, outputStreams{(objData.UsesStringFiles ? ", param.StringsWriter" : null)}));");
                    }
                    else
                    {
                        fg.AppendLine($"toDo.Add(() => Write{field.Name}Parallel(item.{field.Name}, masterRefs, {i}, 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");
                    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))
                {
                    fg.AppendLine("if (group.RecordCache.Count == 0) return;");
                    fg.AppendLine($"var cuts = group.Records.Cut(CutCount).ToArray();");
                    fg.AppendLine($"Stream[] subStreams = new Stream[cuts.Length + 1];");
                    fg.AppendLine($"byte[] groupBytes = new byte[{nameof(GameConstants)}.{obj.GetObjectData().GameMode}.GroupConstants.HeaderLength];");
                    fg.AppendLine($"BinaryPrimitives.WriteInt32LittleEndian(groupBytes.AsSpan(), RecordTypes.GRUP.TypeInt);");
                    fg.AppendLine($"var groupByteStream = new MemoryStream(groupBytes);");
                    fg.AppendLine($"var bundle = new {nameof(WritingBundle)}({nameof(GameConstants)}.{obj.GetObjectData().GameMode})");
                    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(groupByteStream, {nameof(GameConstants)}.{obj.GetObjectData().GameMode}, 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($"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();
            }
        }
Beispiel #6
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();
        }
Beispiel #7
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.Nullable)
                    {
                        conditions.Add($"{field.NullableAccessor(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.Nullable)
                        {
                            fg.AppendLine($"if (item.{dataType.StateName}.HasFlag({obj.Name}.{dataType.EnumName}.Has))");
                        }
                        using (new BraceWrapper(fg, doIt: dataType.Nullable))
                        {
                            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();
        }
        public override async Task GenerateInCommon(ObjectGeneration obj, FileGeneration fg, MaskTypeSet maskTypes)
        {
            if (!maskTypes.Applicable(LoquiInterfaceType.ISetter, CommonGenerics.Class))
            {
                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}void Remove"))
            {
                args.Add($"{obj.Interface(getter: false, internalInterface: true)} obj");
                args.Add($"HashSet<{nameof(FormKey)}> keys");
            }
            using (new BraceWrapper(fg))
            {
                var fgCount = fg.Count;
                foreach (var baseClass in obj.BaseClassTrail())
                {
                    if (await MajorRecordModule.HasMajorRecords(baseClass, includeBaseClass: true, includeSelf: true) != Case.No)
                    {
                        fg.AppendLine($"base.Remove(obj, keys);");
                        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 fieldAccessor = $"{accessor}.{loqui.Name}";
                        if (await MajorRecordModule.HasMajorRecords(loqui.TargetObjectGeneration, includeBaseClass: true, includeSelf: false) != Case.No)
                        {
                            fg.AppendLine($"{fieldAccessor}{loqui.NullChar}.Remove(keys);");
                        }
                        var isMajorRecord = loqui.TargetObjectGeneration != null && await loqui.TargetObjectGeneration.IsMajorRecord();

                        if (isMajorRecord)
                        {
                            fg.AppendLine($"if ({(loqui.Nullable ? $"{fieldAccessor} != null && " : string.Empty)}keys.Contains({fieldAccessor}.FormKey))");
                            using (new BraceWrapper(fg))
                            {
                                fg.AppendLine($"{fieldAccessor} = null;");
                            }
                        }
                    }
                    else if (field is ContainerType cont)
                    {
                        if (!(cont.SubTypeGeneration is LoquiType contLoqui))
                        {
                            continue;
                        }
                        var isMajorRecord = await contLoqui.IsMajorRecord();

                        if (isMajorRecord)
                        {
                            fg.AppendLine($"{accessor}.{field.Name}.Remove(keys);");
                        }
                        if (await MajorRecordModule.HasMajorRecords(contLoqui, includeBaseClass: true, includeSelf: false) != Case.No)
                        {
                            fg.AppendLine($"{accessor}.{field.Name}.ForEach(i => i.Remove(keys));");
                        }
                        if (contLoqui.TargetObjectGeneration?.IsListGroup() ?? false)
                        {
                            fg.AppendLine($"{accessor}.{field.Name}.RemoveWhere(i => i.{contLoqui.TargetObjectGeneration.Fields.FirstOrDefault(f => f is ContainerType).Name}.Count == 0);");
                        }
                    }
                    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:
                            case Case.Maybe:
                                fg.AppendLine($"{accessor}.{field.Name}.Remove(keys);");
                                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);
                        }
                    }
                }
            }
            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 void Remove"))
                    {
                        args.Add($"{baseClass.Interface(getter: false)} obj");
                        args.Add($"HashSet<{nameof(FormKey)}> keys");
                    }
                    using (new BraceWrapper(fg))
                    {
                        using (var args = new ArgsWrapper(fg,
                                                          "Remove"))
                        {
                            args.Add($"({obj.Interface(getter: false)})obj");
                            args.AddPassArg("keys");
                        }
                    }
                    fg.AppendLine();
                }
            }

            using (var args = new FunctionWrapper(fg,
                                                  $"public{overrideStr}void Remove"))
            {
                args.Add($"{obj.Interface(getter: false, internalInterface: true)} obj");
                args.Add($"HashSet<{nameof(FormKey)}> keys");
                args.Add($"Type type");
                args.Add($"bool throwIfUnknown");
            }
            using (new BraceWrapper(fg))
            {
                var fgCount = fg.Count;
                foreach (var baseClass in obj.BaseClassTrail())
                {
                    if (await MajorRecordModule.HasMajorRecords(baseClass, includeBaseClass: true, includeSelf: true) != Case.No)
                    {
                        fg.AppendLine("base.Remove(obj, type, keys);");
                        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\":");
                    }
                    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($"if (!{obj.RegistrationName}.SetterType.IsAssignableFrom(obj.GetType())) return;");
                        fg.AppendLine("this.Remove(obj, keys);");
                        fg.AppendLine("break;");
                    }

                    Dictionary <object, FileGeneration> generationDict = new Dictionary <object, FileGeneration>();
                    foreach (var field in obj.IterateFields())
                    {
                        LoquiType      targetLoqui;
                        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);
                            }
                            targetLoqui = 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);
                            }
                            targetLoqui = 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);
                            }
                            targetLoqui = dictLoqui;
                        }
                        else
                        {
                            continue;
                        }
                        bool applicable = false;
                        switch (targetLoqui.RefType)
                        {
                        case LoquiType.LoquiRefType.Direct:
                            applicable = await targetLoqui.TargetObjectGeneration.IsMajorRecord();

                            break;

                        case LoquiType.LoquiRefType.Interface:
                            applicable = true;
                            break;

                        case LoquiType.LoquiRefType.Generic:
                        default:
                            break;
                        }
                        await ApplyRemovalLines(field, fieldGen, accessor, removeSelf : applicable);
                    }

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

                    if (doAdditionlDeepLogic)
                    {
                        LinkInterfaceModule.ObjectMappings.TryGetValue(obj.ProtoGen.Protocol, out var interfs);

                        var deepRecordMapping = await MajorRecordModule.FindDeepRecords(obj);

                        foreach (var deepRec in deepRecordMapping)
                        {
                            FileGeneration deepFg = generationDict.GetOrAdd(deepRec.Key);
                            foreach (var field in deepRec.Value)
                            {
                                var remSelf = false;
                                switch (field)
                                {
                                case ContainerType cont:
                                    if (cont.SubTypeGeneration is LoquiType loqui)
                                    {
                                        switch (loqui.RefType)
                                        {
                                        case LoquiType.LoquiRefType.Direct:
                                            remSelf = loqui.TargetObjectGeneration == deepRec.Key;
                                            break;

                                        case LoquiType.LoquiRefType.Interface:
                                            if (interfs.TryGetValue(loqui.SetterInterface, out var objs))
                                            {
                                                remSelf = objs.Contains(deepRec.Key);
                                            }
                                            break;

                                        case LoquiType.LoquiRefType.Generic:
                                        default:
                                            break;
                                        }
                                    }
                                    break;

                                default:
                                    break;
                                }

                                remSelf &= await deepRec.Key.IsMajorRecord();
                                await ApplyRemovalLines(field, deepFg, accessor, obj : deepRec.Key, removeSelf : remSelf);
                            }
                        }

                        // Generate for major record marker interfaces
                        foreach (var interf in interfs.EmptyIfNull())
                        {
                            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($"Remove({accessor}, keys, typeof({grup.GetGroupTarget().Interface(getter: true)}), throwIfUnknown: throwIfUnknown);");
                                    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)
                            {
                                bool remSelf = false;
                                switch (deepObj)
                                {
                                case ContainerType cont:
                                    if (cont.SubTypeGeneration is LoquiType loqui)
                                    {
                                        remSelf = loqui.RefType == LoquiType.LoquiRefType.Interface && loqui.Interface(getter: false) == interf.Key;
                                    }
                                    break;

                                default:
                                    break;
                                }
                                await ApplyRemovalLines(deepObj, subFg, accessor, blackList : passedObjects, removeSelf : remSelf);
                            }
                            if (!subFg.Empty)
                            {
                                var genFg = generationDict.GetOrAdd(new InterfInstr()
                                {
                                    Interf = interf.Key
                                });
                                genFg.AppendLines(subFg);
                            }
                        }

                        foreach (var kv in generationDict)
                        {
                            switch (kv.Key)
                            {
                            case LoquiType loqui:
                                if (loqui.RefType == LoquiType.LoquiRefType.Direct)
                                {
                                    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)}\":");
                                    }
                                }
                                else
                                {
                                    continue;
                                }
                                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 InterfInstr interf:
                                fg.AppendLine($"case \"{interf.Interf}\":");
                                fg.AppendLine($"case \"{interf.Interf}Getter\":");
                                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("break;");
                            }
                        }
                    }

                    fg.AppendLine("default:");
                    using (new DepthWrapper(fg))
                    {
                        if (generationDict.TryGetValue("default:", out var gen))
                        {
                            fg.AppendLines(gen);
                            fg.AppendLine("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("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 void Remove"))
                    {
                        args.Add($"{baseClass.Interface(getter: false)} obj");
                        args.Add($"HashSet<{nameof(FormKey)}> keys");
                        args.Add($"Type type");
                        args.Add($"bool throwIfUnknown");
                    }
                    using (new BraceWrapper(fg))
                    {
                        using (var args = new ArgsWrapper(fg,
                                                          "Remove"))
                        {
                            args.Add($"({obj.Interface(getter: false)})obj");
                            args.AddPassArg("keys");
                            args.AddPassArg("type");
                            args.AddPassArg("throwIfUnknown");
                        }
                    }
                    fg.AppendLine();
                }
            }
        }
Beispiel #9
0
    public virtual void GenerateWriteToNode(ObjectGeneration obj, StructuredStringBuilder sb)
    {
        using (var args = new Function(sb,
                                       $"public static void WriteToNode{ModuleNickname}{obj.GetGenericTypes(MaskType.Normal)}"))
        {
            args.Add($"{obj.Interface(internalInterface: true, getter: true)} item");
            args.Add($"XElement {XElementLine.GetParameterName(obj, Context.Backend)}");
            args.Add($"ErrorMaskBuilder? errorMask");
            args.Add($"{nameof(TranslationCrystal)}? translationMask");
        }
        using (sb.CurlyBrace())
        {
            if (obj.HasLoquiBaseObject)
            {
                using (var args = sb.Call(
                           $"{TranslationWriteClass(obj.BaseClass)}.WriteToNode{ModuleNickname}"))
                {
                    args.Add($"item: item");
                    args.Add($"{XElementLine.GetParameterName(obj, Context.Backend)}: {XElementLine.GetParameterName(obj, Context.Backend)}");
                    args.Add($"errorMask: errorMask");
                    args.Add($"translationMask: translationMask");
                }
            }
            foreach (var field in obj.IterateFieldIndices())
            {
                if (!TryGetTypeGeneration(field.Field.GetType(), out var generator))
                {
                    throw new ArgumentException("Unsupported type generator: " + field.Field);
                }

                if (!generator.ShouldGenerateWrite(field.Field))
                {
                    continue;
                }

                List <string> conditions = new List <string>();
                if (field.Field.Nullable)
                {
                    conditions.Add($"{field.Field.NullableAccessor(getter: true, accessor: Accessor.FromType(field.Field, "item"))}");
                }
                if (TranslationMaskParameter)
                {
                    conditions.Add(field.Field.GetTranslationIfAccessor("translationMask"));
                }
                if (conditions.Count > 0)
                {
                    using (var args = sb.If(ands: true))
                    {
                        foreach (var item in conditions)
                        {
                            args.Add(item);
                        }
                    }
                }
                using (sb.CurlyBrace(doIt: conditions.Count > 0))
                {
                    var maskType = Gen.MaskModule.GetMaskModule(field.Field.GetType()).GetErrorMaskTypeStr(field.Field);
                    generator.GenerateWrite(
                        sb: sb,
                        objGen: obj,
                        typeGen: field.Field,
                        writerAccessor: $"{XElementLine.GetParameterName(obj, Context.Backend)}",
                        itemAccessor: Accessor.FromType(field.Field, "item"),
                        errorMaskAccessor: $"errorMask",
                        translationMaskAccessor: "translationMask",
                        nameAccessor: $"nameof(item.{field.Field.Name})");
                }
            }
        }
        sb.AppendLine();
    }
Beispiel #10
0
    protected virtual void FillPublicElement(ObjectGeneration obj, StructuredStringBuilder sb)
    {
        using (var args = new Function(sb,
                                       $"public static void FillPublicElement{ModuleNickname}"))
        {
            args.Add($"{obj.Interface(getter: false)} item");
            args.Add($"XElement {XElementLine.GetParameterName(obj, Context.Backend)}");
            args.Add("string name");
            args.Add($"ErrorMaskBuilder? errorMask");
            args.Add($"{nameof(TranslationCrystal)}? translationMask");
        }
        using (sb.CurlyBrace())
        {
            sb.AppendLine("switch (name)");
            using (sb.CurlyBrace())
            {
                foreach (var field in obj.IterateFields())
                {
                    if (field.Derivative)
                    {
                        continue;
                    }
                    if (field.ReadOnly)
                    {
                        continue;
                    }
                    if (!TryGetTypeGeneration(field.GetType(), out var generator))
                    {
                        throw new ArgumentException("Unsupported type generator: " + field);
                    }

                    sb.AppendLine($"case \"{field.Name}\":");
                    using (sb.IncreaseDepth())
                    {
                        if (generator.ShouldGenerateCopyIn(field))
                        {
                            List <string> conditions = new List <string>();
                            if (TranslationMaskParameter)
                            {
                                conditions.Add(field.GetTranslationIfAccessor("translationMask"));
                            }
                            if (conditions.Count > 0)
                            {
                                using (var args = sb.If(ands: true))
                                {
                                    foreach (var item in conditions)
                                    {
                                        args.Add(item);
                                    }
                                }
                            }
                            using (sb.CurlyBrace(doIt: conditions.Count > 0))
                            {
                                generator.GenerateCopyIn(
                                    sb: sb,
                                    objGen: obj,
                                    typeGen: field,
                                    nodeAccessor: XElementLine.GetParameterName(obj, Context.Backend).Result,
                                    itemAccessor: Accessor.FromType(field, "item"),
                                    translationMaskAccessor: "translationMask",
                                    errorMaskAccessor: $"errorMask");
                            }
                        }
                        sb.AppendLine("break;");
                    }
                }

                sb.AppendLine("default:");
                using (sb.IncreaseDepth())
                {
                    if (obj.HasLoquiBaseObject)
                    {
                        using (var args = sb.Call(
                                   $"{obj.BaseClass.CommonClassName(LoquiInterfaceType.ISetter)}.FillPublicElement{ModuleNickname}{obj.GetBaseMask_GenericTypes(MaskType.Error)}"))
                        {
                            args.Add("item: item");
                            args.Add($"{XElementLine.GetParameterName(obj, Context.Backend)}: {XElementLine.GetParameterName(obj, Context.Backend)}");
                            args.Add("name: name");
                            args.Add("errorMask: errorMask");
                            if (TranslationMaskParameter)
                            {
                                args.Add($"translationMask: translationMask");
                            }
                        }
                    }
                    sb.AppendLine("break;");
                }
            }
        }
        sb.AppendLine();
    }
Beispiel #11
0
        public override async Task PostLoad(ObjectGeneration obj)
        {
            await base.PostLoad(obj);

            if (obj.Abstract || !await obj.IsMajorRecord())
            {
                return;
            }
            obj.Interfaces.Add(LoquiInterfaceDefinitionType.IGetter, $"IMapsToGetter<{obj.Interface(getter: true, internalInterface: false)}>");
        }
Beispiel #12
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();
        }
Beispiel #13
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();
                }
            }
        }
Beispiel #14
0
        public override async Task PreLoad(ObjectGeneration obj)
        {
            if (obj.GetObjectType() != ObjectType.Mod)
            {
                return;
            }
            var elems = obj.Node.Elements(XName.Get(GameReleaseOptions, LoquiGenerator.Namespace));

            if (!elems.Any())
            {
                return;
            }
            var objData = obj.GetObjectData();

            objData.GameReleaseOptions = elems.Select(el => Enum.Parse <GameRelease>(el.Value)).ToHashSet();
            obj.Interfaces.Add(LoquiInterfaceDefinitionType.IGetter, $"IMajorRecordContextEnumerable<{obj.Interface(getter: false, internalInterface: true)}, {obj.Interface(getter: true, internalInterface: true)}>");
        }
Beispiel #15
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();
        }
Beispiel #16
0
        public override async Task GenerateInCommon(ObjectGeneration obj, FileGeneration fg, MaskTypeSet maskTypes)
        {
            if (maskTypes.Applicable(LoquiInterfaceType.IGetter, CommonGenerics.Class))
            {
                fg.AppendLine($"public IEnumerable<{nameof(FormLinkInformation)}> GetContainedFormLinks({obj.Interface(getter: true)} obj)");
                using (new BraceWrapper(fg))
                {
                    foreach (var baseClass in obj.BaseClassTrail())
                    {
                        if (await HasLinks(baseClass, includeBaseClass: true) != LinkCase.No)
                        {
                            fg.AppendLine("foreach (var item in base.GetContainedFormLinks(obj))");
                            using (new BraceWrapper(fg))
                            {
                                fg.AppendLine("yield return item;");
                            }
                            break;
                        }
                    }
                    var startCount = fg.Count;
                    foreach (var field in obj.IterateFields(nonIntegrated: true))
                    {
                        if (field is FormLinkType formLink)
                        {
                            if (field.Nullable)
                            {
                                fg.AppendLine($"if (obj.{field.Name}.{formLink.FormIDTypeString}.HasValue)");
                                using (new BraceWrapper(fg))
                                {
                                    fg.AppendLine($"yield return {nameof(FormLinkInformation)}.{nameof(FormLinkInformation.Factory)}(obj.{field.Name});");
                                }
                            }
                            else if (formLink.FormIDType == FormLinkType.FormIDTypeEnum.Normal)
                            {
                                fg.AppendLine($"yield return {nameof(FormLinkInformation)}.{nameof(FormLinkInformation.Factory)}(obj.{field.Name});");
                            }
                        }
                        else if (field is LoquiType loqui)
                        {
                            LinkCase subLinkCase;
                            if (loqui.TargetObjectGeneration != null)
                            {
                                subLinkCase = await HasLinks(loqui, includeBaseClass : true);
                            }
                            else
                            {
                                subLinkCase = LinkCase.Maybe;
                            }
                            if (subLinkCase == LinkCase.No)
                            {
                                continue;
                            }
                            var doBrace = true;
                            var access  = $"obj.{field.Name}";
                            if (subLinkCase == LinkCase.Maybe)
                            {
                                fg.AppendLine($"if (obj.{field.Name} is {nameof(IFormLinkContainerGetter)} {field.Name}linkCont)");
                                access = $"{field.Name}linkCont";
                            }
                            else if (loqui.Nullable)
                            {
                                fg.AppendLine($"if (obj.{field.Name}.TryGet(out var {field.Name}Items))");
                                access = $"{field.Name}Items";
                            }
                            else
                            {
                                doBrace = false;
                            }
                            using (new BraceWrapper(fg, doIt: doBrace))
                            {
                                fg.AppendLine($"foreach (var item in {access}.{nameof(IFormLinkContainerGetter.ContainedFormLinks)})");
                                using (new BraceWrapper(fg))
                                {
                                    fg.AppendLine($"yield return item;");
                                }
                            }
                        }
                        else if (field is WrapperType cont)
                        {
                            var access = $"obj.{field.Name}";
                            if (field.Nullable)
                            {
                                access = $"{field.Name}Item";
                            }

                            FileGeneration subFg = new FileGeneration();
                            if (cont.SubTypeGeneration is LoquiType contLoqui &&
                                await HasLinks(contLoqui, includeBaseClass: true) != LinkCase.No)
                            {
                                string filterNulls = cont is GenderedType && ((GenderedType)cont).ItemNullable ? ".NotNull()" : null;
                                var    linktype    = await HasLinks(contLoqui, includeBaseClass : true);

                                if (linktype != LinkCase.No)
                                {
                                    switch (linktype)
                                    {
                                    case LinkCase.Yes:
                                        subFg.AppendLine($"foreach (var item in {access}{filterNulls}.SelectMany(f => f.{nameof(IFormLinkContainerGetter.ContainedFormLinks)}))");
                                        break;

                                    case LinkCase.Maybe:
                                        subFg.AppendLine($"foreach (var item in {access}{filterNulls}.WhereCastable<{contLoqui.TypeName(getter: true)}, {nameof(IFormLinkContainerGetter)}>()");
                                        using (new DepthWrapper(subFg))
                                        {
                                            subFg.AppendLine($".SelectMany((f) => f.{nameof(IFormLinkContainerGetter.ContainedFormLinks)}))");
                                        }
                                        break;

                                    default:
                                        throw new NotImplementedException();
                                    }
                                }
                            }
                            else if (cont.SubTypeGeneration is FormLinkType formIDType &&
                                     formIDType.FormIDType == FormLinkType.FormIDTypeEnum.Normal)
                            {
                                string filterNulls = cont is GenderedType && ((GenderedType)cont).ItemNullable ? ".NotNull()" : null;
                                subFg.AppendLine($"foreach (var item in {access}{filterNulls})");
                            }
                            else
                            {
                                continue;
                            }

                            if (field.Nullable)
                            {
                                fg.AppendLine($"if (obj.{field.Name}.TryGet(out var {field.Name}Item))");
                            }
                            using (new BraceWrapper(fg, doIt: field.Nullable))
                            {
                                fg.AppendLines(subFg);
                                using (new BraceWrapper(fg))
                                {
                                    fg.AppendLine($"yield return {nameof(FormLinkInformation)}.{nameof(FormLinkInformation.Factory)}(item);");
                                }
                            }
                        }
Beispiel #17
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 ? $", item.FormVersion" : 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: true)})item");
                            args.AddPassArg("formKey");
                            args.AddPassArg("copyMask");
                        }
                    }
                    fg.AppendLine();
                }
            }
        }
        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(IMajorRecordCommonGetter)}");
            }
            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(IMajorRecordCommonGetter)}");
            }
            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(IMajorRecordCommonGetter)}");
            }
            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(IMajorRecordCommonGetter)}");
            }
            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(IMajorRecordCommonGetter)}");
            }
            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();
        }
Beispiel #19
0
        public override async Task GenerateInVoid(ObjectGeneration obj, FileGeneration fg)
        {
            if (obj.GetObjectType() != ObjectType.Mod)
            {
                return;
            }
            using (new NamespaceWrapper(fg, obj.Namespace))
            {
                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))
                {
                }
            }
        }