public override async Task GenerateInCommon(ObjectGeneration obj, FileGeneration fg, MaskTypeSet maskTypes) { if (!await obj.IsMajorRecord()) { return; } if (!maskTypes.Applicable(LoquiInterfaceType.IGetter, CommonGenerics.Class, MaskType.Normal)) { return; } //ToDo // Modify to getter interface after copy is refactored fg.AppendLine($"partial void PostDuplicate({obj.Name} obj, {obj.ObjectName} rhs, Func<FormKey> getNextFormKey, IList<({nameof(IMajorRecordCommon)} Record, FormKey OriginalFormKey)>? duplicatedRecords);"); fg.AppendLine(); fg.AppendLine($"public{obj.FunctionOverride()}{nameof(IMajorRecordCommon)} Duplicate({nameof(IMajorRecordCommonGetter)} item, Func<FormKey> getNextFormKey, IList<({nameof(IMajorRecordCommon)} Record, FormKey OriginalFormKey)>? duplicatedRecords)"); using (new BraceWrapper(fg)) { if (obj.Abstract) { fg.AppendLine($"throw new {nameof(NotImplementedException)}();"); } else { fg.AppendLine($"var ret = new {obj.Name}(getNextFormKey());"); //ToDo // Modify to getter interface after copy is refactored fg.AppendLine($"ret.DeepCopyIn(({obj.ObjectName})item);"); fg.AppendLine("duplicatedRecords?.Add((ret, item.FormKey));"); fg.AppendLine($"PostDuplicate(ret, ({obj.ObjectName})item, getNextFormKey, duplicatedRecords);"); fg.AppendLine("return ret;"); } } fg.AppendLine(); }
public override async Task GenerateInCommon(ObjectGeneration obj, StructuredStringBuilder sb, MaskTypeSet maskTypes) { if (maskTypes.Applicable(LoquiInterfaceType.ISetter, CommonGenerics.Class, MaskType.Normal)) { FillPrivateElement(obj, sb); } await base.GenerateInCommon(obj, sb, maskTypes); }
public override async Task GenerateInCommon(ObjectGeneration obj, FileGeneration fg, MaskTypeSet maskTypes) { await base.GenerateInCommon(obj, fg, maskTypes); if (obj.GetObjectType() != ObjectType.Mod) { return; } if (!maskTypes.Applicable(LoquiInterfaceType.IGetter, CommonGenerics.Class, MaskType.Normal)) { return; } GenerateGetGroup(obj, fg); GenerateWriteParallel(obj, fg); }
public override async Task GenerateInCommon(ObjectGeneration obj, FileGeneration fg, MaskTypeSet maskTypes) { if (maskTypes.Applicable(LoquiInterfaceType.IGetter, CommonGenerics.Class)) { fg.AppendLine($"public IEnumerable<{nameof(IFormLinkGetter)}> GetContainedFormLinks({obj.Interface(getter: true)} obj)"); using (new BraceWrapper(fg)) { foreach (var baseClass in obj.BaseClassTrail()) { if (await HasLinks(baseClass, includeBaseClass: true) != Case.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 FormKeyType formKey && obj.Name != "MajorRecord") { if (field.Nullable) { fg.AppendLine($"if (obj.{field.Name} != null)"); using (new BraceWrapper(fg)) { fg.AppendLine($"yield return {nameof(FormLinkInformation)}.{nameof(FormLinkInformation.Factory)}(obj.{field.Name}.AsLink<I{obj.ProtoGen.Protocol.Namespace}MajorRecordGetter>());"); } } else { fg.AppendLine($"yield return {nameof(FormLinkInformation)}.{nameof(FormLinkInformation.Factory)}(obj.{field.Name}.AsLink<I{obj.ProtoGen.Protocol.Namespace}MajorRecordGetter>());"); } } else if (field is LoquiType loqui) { Case subLinkCase; if (loqui.TargetObjectGeneration != null) { subLinkCase = await HasLinks(loqui, includeBaseClass : true); } else { subLinkCase = Case.Maybe; } if (subLinkCase == Case.No) { continue; } var doBrace = true; var access = $"obj.{field.Name}"; if (subLinkCase == Case.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} is {{}} {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) != Case.No) { string filterNulls = cont is GenderedType && ((GenderedType)cont).ItemNullable ? ".NotNull()" : null; var linktype = await HasLinks(contLoqui, includeBaseClass : true); if (linktype != Case.No) { switch (linktype) { case Case.Yes: subFg.AppendLine($"foreach (var item in {access}{filterNulls}.SelectMany(f => f.{nameof(IFormLinkContainerGetter.ContainedFormLinks)}))"); break; case Case.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})"); }
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(); } } }
public override async Task GenerateInCommon(ObjectGeneration obj, FileGeneration fg, MaskTypeSet maskTypes) { if (!maskTypes.Applicable(LoquiInterfaceType.IGetter, CommonGenerics.Class)) { return; } fg.AppendLine($"public IEnumerable<{nameof(FormKey)}> GetLinkFormKeys({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.GetLinkFormKeys(obj))"); using (new BraceWrapper(fg)) { fg.AppendLine("yield return item;"); } break; } } foreach (var field in obj.IterateFields()) { if (field is FormLinkType formLink) { if (field.HasBeenSet) { fg.AppendLine($"if (obj.{field.Name}.FormKey.TryGet(out var {field.Name}Key))"); using (new BraceWrapper(fg)) { fg.AppendLine($"yield return {field.Name}Key;"); } } else if (formLink.FormIDType == FormLinkType.FormIDTypeEnum.Normal) { fg.AppendLine($"yield return obj.{field.Name}.FormKey;"); } } 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(ILinkedFormKeyContainer)} {field.Name}linkCont)"); access = $"{field.Name}linkCont"; } else if (loqui.HasBeenSet) { 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(ILinkedFormKeyContainer.LinkFormKeys)})"); using (new BraceWrapper(fg)) { fg.AppendLine($"yield return item;"); } } } else if (field is ContainerType cont) { var access = $"obj.{field.Name}"; if (field.HasBeenSet) { access = $"{field.Name}Item"; } FileGeneration subFg = new FileGeneration(); if (cont.SubTypeGeneration is LoquiType contLoqui && await HasLinks(contLoqui, includeBaseClass: true) != LinkCase.No) { var linktype = await HasLinks(contLoqui, includeBaseClass : true); if (linktype != LinkCase.No) { switch (linktype) { case LinkCase.Yes: subFg.AppendLine($"foreach (var item in {access}.SelectMany(f => f.{nameof(ILinkedFormKeyContainer.LinkFormKeys)}))"); break; case LinkCase.Maybe: subFg.AppendLine($"foreach (var item in {access}.WhereCastable<{contLoqui.TypeName(getter: true)}, {nameof(ILinkedFormKeyContainer)}> ()"); using (new DepthWrapper(subFg)) { subFg.AppendLine($".SelectMany((f) => f.{nameof(ILinkedFormKeyContainer.LinkFormKeys)}))"); } break; default: throw new NotImplementedException(); } } } else if (cont.SubTypeGeneration is FormLinkType formIDType && formIDType.FormIDType == FormLinkType.FormIDTypeEnum.Normal) { subFg.AppendLine($"foreach (var item in {access}.Select(f => f.FormKey))"); }
public override async Task GenerateInCommon(ObjectGeneration obj, FileGeneration fg, MaskTypeSet maskTypes) { if (!maskTypes.Applicable(LoquiInterfaceType.IGetter, CommonGenerics.Class)) { return; } await base.GenerateInCommon(obj, fg, maskTypes); if (!await obj.IsMajorRecord()) { return; } using (new RegionWrapper(fg, "Duplicate")) { using (var args = new FunctionWrapper(fg, $"public{obj.Virtual()}{obj.Name} Duplicate{obj.GetGenericTypes(MaskType.Normal, MaskType.NormalGetter)}")) { args.Wheres.AddRange(obj.GenericTypeMaskWheres(LoquiInterfaceType.IGetter, MaskType.Normal, MaskType.NormalGetter)); args.Add($"{obj.Interface(getter: true)} item"); args.Add($"{nameof(FormKey)} formKey"); args.Add($"TranslationCrystal? copyMask"); } using (new BraceWrapper(fg)) { if (obj.Abstract) { fg.AppendLine("throw new NotImplementedException();"); } else { fg.AppendLine($"var newRec = new {obj.Name}(formKey{(obj.GetObjectData().HasMultipleReleases ? $", default({obj.GetObjectData().GameCategory}Release)" : null)});"); fg.AppendLine($"newRec.DeepCopyIn(item, default({nameof(ErrorMaskBuilder)}?), copyMask);"); fg.AppendLine("return newRec;"); } } fg.AppendLine(); foreach (var baseClass in obj.BaseClassTrail()) { using (var args = new FunctionWrapper(fg, $"public override {baseClass.Name} Duplicate{baseClass.GetGenericTypes(MaskType.Normal, MaskType.NormalGetter)}")) { args.Wheres.AddRange(baseClass.GenericTypeMaskWheres(LoquiInterfaceType.IGetter, MaskType.Normal, MaskType.NormalGetter)); args.Add($"{baseClass.Interface(getter: true)} item"); args.Add($"{nameof(FormKey)} formKey"); args.Add($"TranslationCrystal? copyMask"); } using (new BraceWrapper(fg)) { using (var args = new ArgsWrapper(fg, $"return this.Duplicate")) { args.Add($"item: ({obj.Interface(getter: false)})item"); args.AddPassArg("formKey"); args.AddPassArg("copyMask"); } } fg.AppendLine(); } } }
public override async Task GenerateInCommon(ObjectGeneration obj, FileGeneration fg, MaskTypeSet maskTypes) { bool getter = maskTypes.Applicable(LoquiInterfaceType.IGetter, CommonGenerics.Class); if (!getter) { return; } var accessor = new Accessor("obj"); if (obj.Abstract) { return; } if (obj.GetObjectType() == ObjectType.Group) { return; } if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No) { return; } var overrideStr = await obj.FunctionOverride(async c => await MajorRecordModule.HasMajorRecords(c, includeBaseClass : false, includeSelf : true) != Case.No); using (var args = new FunctionWrapper(fg, $"public{overrideStr}IEnumerable<IModContext<{obj.GetObjectData().GameCategory.Value.ModInterface(getter: false)}, IMajorRecordCommon, IMajorRecordCommonGetter>> EnumerateMajorRecordContexts")) { args.Add($"{obj.Interface(getter: getter, internalInterface: true)} obj"); args.Add($"{nameof(ILinkCache)} linkCache"); args.Add($"Type type"); if (obj.GetObjectType() != ObjectType.Mod) { args.Add($"{nameof(ModKey)} modKey"); args.Add($"IModContext? parent"); } args.Add($"bool throwIfUnknown"); if (obj.GetObjectType() == ObjectType.Record) { args.Add($"Func<{obj.GetObjectData().GameCategory.Value.ModInterface(getter: false)}, {obj.Interface(getter: true)}, {obj.Interface(getter: false)}> getter"); } } using (new BraceWrapper(fg)) { if (obj.GetObjectType() == ObjectType.Record) { using (var args = new ArgsWrapper(fg, $"var curContext = new ModContext<{obj.GetObjectData().GameCategory.Value.ModInterface(getter: false)}, {obj.Interface(getter: false)}, {obj.Interface(getter: true)}>")) { args.Add($"{(obj.GetObjectType() == ObjectType.Mod ? "obj.ModKey" : "modKey")}"); args.Add("record: obj"); args.AddPassArg("getter"); args.AddPassArg("parent"); } } var fgCount = fg.Count; fg.AppendLine("switch (type.Name)"); using (new BraceWrapper(fg)) { var gameCategory = obj.GetObjectData().GameCategory; Dictionary <object, FileGeneration> generationDict = new Dictionary <object, FileGeneration>(); foreach (var field in obj.IterateFields()) { FileGeneration fieldGen; if (field is LoquiType loqui) { if (loqui.TargetObjectGeneration.IsListGroup()) { continue; } var isMajorRecord = loqui.TargetObjectGeneration != null && await loqui.TargetObjectGeneration.IsMajorRecord(); if (!isMajorRecord && await MajorRecordModule.HasMajorRecords(loqui, includeBaseClass: true) == Case.No) { continue; } if (loqui.TargetObjectGeneration.GetObjectType() == ObjectType.Group) { fieldGen = generationDict.GetOrAdd(loqui.GetGroupTarget()); } else { fieldGen = generationDict.GetOrAdd(((object)loqui?.TargetObjectGeneration) ?? loqui); } } else if (field is ContainerType cont) { if (!(cont.SubTypeGeneration is LoquiType contLoqui)) { continue; } if (contLoqui.RefType == LoquiType.LoquiRefType.Generic) { fieldGen = generationDict.GetOrAdd("default:"); } else { fieldGen = generationDict.GetOrAdd(((object)contLoqui?.TargetObjectGeneration) ?? contLoqui); } } else if (field is DictType dict) { if (dict.Mode != DictMode.KeyedValue) { continue; } if (!(dict.ValueTypeGen is LoquiType dictLoqui)) { continue; } if (dictLoqui.RefType == LoquiType.LoquiRefType.Generic) { fieldGen = generationDict.GetOrAdd("default:"); } else { fieldGen = generationDict.GetOrAdd(((object)dictLoqui?.TargetObjectGeneration) ?? dictLoqui); } } else { continue; } await ApplyIterationLines(obj, field, fieldGen, accessor, getter); } bool doAdditionlDeepLogic = obj.Name != "ListGroup"; if (doAdditionlDeepLogic) { var deepRecordMapping = await MajorRecordModule.FindDeepRecords(obj); foreach (var deepRec in deepRecordMapping) { FileGeneration deepFg = generationDict.GetOrAdd(deepRec.Key); foreach (var field in deepRec.Value) { await ApplyIterationLines(obj, field, deepFg, accessor, getter, hasTarget : true, includeSelf : false); } } HashSet <string> blackList = new HashSet <string>(); foreach (var kv in generationDict) { switch (kv.Key) { case LoquiType loqui: if (loqui.RefType == LoquiType.LoquiRefType.Generic) { // Handled in default case continue; } else { fg.AppendLine($"case \"{loqui.Interface(getter: true)}\":"); fg.AppendLine($"case \"{loqui.Interface(getter: false)}\":"); if (loqui.HasInternalGetInterface) { fg.AppendLine($"case \"{loqui.Interface(getter: true, internalInterface: true)}\":"); } if (loqui.HasInternalSetInterface) { fg.AppendLine($"case \"{loqui.Interface(getter: false, internalInterface: true)}\":"); } if (loqui.RefType == LoquiType.LoquiRefType.Interface) { blackList.Add(loqui.SetterInterface); } } break; case ObjectGeneration targetObj: fg.AppendLine($"case \"{targetObj.ObjectName}\":"); fg.AppendLine($"case \"{targetObj.Interface(getter: true)}\":"); fg.AppendLine($"case \"{targetObj.Interface(getter: false)}\":"); if (targetObj.HasInternalGetInterface) { fg.AppendLine($"case \"{targetObj.Interface(getter: true, internalInterface: true)}\":"); } if (targetObj.HasInternalSetInterface) { fg.AppendLine($"case \"{targetObj.Interface(getter: false, internalInterface: true)}\":"); } break; case string str: if (str != "default:") { throw new NotImplementedException(); } continue; default: throw new NotImplementedException(); } using (new DepthWrapper(fg)) { fg.AppendLines(kv.Value); fg.AppendLine("yield break;"); } } // Generate for major record marker interfaces if (LinkInterfaceModule.ObjectMappings.TryGetValue(obj.ProtoGen.Protocol, out var interfs)) { foreach (var interf in interfs) { if (blackList.Contains(interf.Key)) { continue; } FileGeneration subFg = new FileGeneration(); HashSet <ObjectGeneration> passedObjects = new HashSet <ObjectGeneration>(); HashSet <TypeGeneration> deepObjects = new HashSet <TypeGeneration>(); foreach (var subObj in interf.Value) { var grup = obj.Fields .WhereCastable <TypeGeneration, GroupType>() .Where(g => g.GetGroupTarget() == subObj) .FirstOrDefault(); if (grup != null) { subFg.AppendLine($"foreach (var item in EnumerateMajorRecordContexts({accessor}, linkCache, typeof({grup.GetGroupTarget().Interface(getter: true)}), throwIfUnknown: throwIfUnknown))"); using (new BraceWrapper(subFg)) { subFg.AppendLine("yield return item;"); } passedObjects.Add(grup.GetGroupTarget()); } else if (deepRecordMapping.TryGetValue(subObj, out var deepRec)) { foreach (var field in deepRec) { deepObjects.Add(field); } } } foreach (var deepObj in deepObjects) { await ApplyIterationLines(obj, deepObj, subFg, accessor, getter, blackList : passedObjects, hasTarget : true, includeSelf : false); } if (!subFg.Empty) { fg.AppendLine($"case \"{interf.Key}\":"); fg.AppendLine($"case \"{interf.Key}Getter\":"); using (new BraceWrapper(fg)) { fg.AppendLines(subFg); fg.AppendLine("yield break;"); } } } } } fg.AppendLine("default:"); using (new DepthWrapper(fg)) { if (generationDict.TryGetValue("default:", out var gen)) { fg.AppendLines(gen); fg.AppendLine("yield break;"); } else { fg.AppendLine("if (throwIfUnknown)"); using (new BraceWrapper(fg)) { fg.AppendLine("throw new ArgumentException($\"Unknown major record type: {type}\");"); } fg.AppendLine($"else"); using (new BraceWrapper(fg)) { fg.AppendLine("yield break;"); } } } } } fg.AppendLine(); }
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(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)}\":"); 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.EndsWith("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(); } } }