public virtual async Task GenerateWrapperRecordTypeParse( FileGeneration fg, ObjectGeneration objGen, TypeGeneration typeGen, Accessor locationAccessor, Accessor packageAccessor, Accessor converterAccessor) { switch (typeGen.GetFieldData().BinaryOverlayFallback) { case BinaryGenerationType.Normal: fg.AppendLine($"_{typeGen.Name}Location = {locationAccessor};"); break; case BinaryGenerationType.Custom: using (var args = new ArgsWrapper(fg, $"{typeGen.Name}CustomParse")) { args.AddPassArg($"stream"); args.AddPassArg($"finalPos"); args.AddPassArg($"offset"); } break; case BinaryGenerationType.NoGeneration: default: return; } }
public override async Task GenerateInCommonMixin(ObjectGeneration obj, FileGeneration fg) { if (!await obj.IsMajorRecord()) { return; } if (!obj.IsTopClass) { return; } using (var args = new FunctionWrapper(fg, $"public static {nameof(IMajorRecordCommon)} {nameof(IDuplicatable.Duplicate)}")) { //ToDo // Modify to getter interface after copy is refactored args.Add($"this {obj.ObjectName} item"); args.Add("Func<FormKey> getNextFormKey"); args.Add($"IList<({nameof(IMajorRecordCommon)} Record, FormKey OriginalFormKey)>? duplicatedRecords = null"); } using (new BraceWrapper(fg)) { using (var args = new ArgsWrapper(fg, $"return {obj.CommonClassInstance("item", LoquiInterfaceType.IGetter, CommonGenerics.Class, MaskType.Normal)}.{nameof(IDuplicatable.Duplicate)}")) { args.AddPassArg("item"); args.AddPassArg("getNextFormKey"); args.AddPassArg("duplicatedRecords"); } } }
public override async Task GenerateInCommonMixin(ObjectGeneration obj, FileGeneration fg) { await base.GenerateInCommonMixin(obj, fg); if (!await obj.IsMajorRecord()) { return; } using (var args = new FunctionWrapper(fg, $"public static {obj.ObjectName} Duplicate{obj.GetGenericTypes(MaskType.Normal, MaskType.NormalGetter)}")) { args.Wheres.AddRange(obj.GenericTypeMaskWheres(LoquiInterfaceType.IGetter, MaskType.Normal, MaskType.NormalGetter)); args.Add($"this {obj.Interface(obj.GetGenericTypes(MaskType.NormalGetter), getter: true, internalInterface: true)} item"); args.Add($"{nameof(FormKey)} formKey"); args.Add($"{obj.Mask(MaskType.Translation)}? copyMask = null"); } using (new BraceWrapper(fg)) { using (var args = new ArgsWrapper(fg, $"return {obj.CommonClassInstance("item", LoquiInterfaceType.IGetter, CommonGenerics.Functions, MaskType.NormalGetter)}.Duplicate{obj.GetGenericTypes(MaskType.Normal, MaskType.NormalGetter, MaskType.Translation)}")) { args.AddPassArg("item"); args.AddPassArg("formKey"); args.Add("copyMask: copyMask?.GetCrystal()"); } } fg.AppendLine(); }
private void GenerateCustomBinaryEndCreatePartial(ObjectGeneration obj, FileGeneration fg) { var data = obj.GetObjectData(); if (data.CustomBinaryEnd == CustomEnd.Off) { return; } if (data.CustomBinaryEnd == CustomEnd.Normal) { using (var args = new ArgsWrapper(fg, $"public static partial void CustomBinaryEndImport")) { args.Add($"{ReaderClass} {ReaderMemberName}"); args.Add($"{obj.Interface(getter: false, internalInterface: true)} obj"); } using (var args = new FunctionWrapper(fg, $"public static void CustomBinaryEndImportPublic")) { args.Add($"{ReaderClass} {ReaderMemberName}"); args.Add($"{obj.Interface(getter: false, internalInterface: true)} obj"); } using (new BraceWrapper(fg)) { using (var args = new ArgsWrapper(fg, $"CustomBinaryEndImport")) { args.AddPassArg(ReaderMemberName); args.AddPassArg($"obj"); } } } }
protected override async Task GenerateNewSnippet(ObjectGeneration obj, FileGeneration fg) { if (await obj.IsMajorRecord()) { fg.AppendLine($"var ret = new {obj.Name}();"); } else { if (obj.TryGetCustomRecordTypeTriggers(out var customLogicTriggers)) { using (var args = new ArgsWrapper(fg, $"var nextRecord = HeaderTranslation.GetNext{(obj.GetObjectType() == ObjectType.Subrecord ? "Subrecord" : "Record")}Type")) { args.Add($"reader: {ReaderMemberName}.Reader"); args.Add("contentLength: out var customLen"); } fg.AppendLine("nextRecord = recordTypeConverter.ConvertToCustom(nextRecord);"); fg.AppendLine("switch (nextRecord.TypeInt)"); using (new BraceWrapper(fg)) { foreach (var item in customLogicTriggers) { fg.AppendLine($"case {item.TypeInt}: // {item.Type}"); } using (new DepthWrapper(fg)) { using (var args = new ArgsWrapper(fg, "return CustomRecordTypeTrigger")) { args.Add($"{ReaderMemberName}: {ReaderMemberName}.SpawnWithLength(customLen + {ReaderMemberName}.{nameof(MutagenFrame.MetaData)}.{nameof(ParsingBundle.Constants)}.{nameof(GameConstants.SubConstants)}.{nameof(GameConstants.SubConstants.HeaderLength)})"); args.Add("recordType: nextRecord"); args.AddPassArg("recordTypeConverter"); } } fg.AppendLine("default:"); using (new DepthWrapper(fg)) { fg.AppendLine("break;"); } } } using (var args = new ArgsWrapper(fg, $"var ret = new {obj.Name}{obj.GetGenericTypes(MaskType.Normal)}")) { if (obj.GetObjectType() == ObjectType.Mod) { args.AddPassArg("modKey"); } if (obj.GetObjectData().GameReleaseOptions != null) { args.AddPassArg("release"); } } if (obj.GetObjectType() == ObjectType.Mod) { fg.AppendLine($"{ReaderMemberName}.MetaData.ModKey = modKey;"); } } }
public override async Task GenerateCopyIn( FileGeneration fg, ObjectGeneration objGen, TypeGeneration typeGen, Accessor frameAccessor, Accessor itemAccessor, Accessor errorMaskAccessor, Accessor translationMaskAccessor) { var loqui = typeGen as LoquiType; var data = loqui.GetFieldData(); if (data.MarkerType.HasValue && !data.RecordType.HasValue) { fg.AppendLine($"frame.Position += frame.{nameof(MutagenFrame.MetaData)}.{nameof(ParsingBundle.Constants)}.{nameof(GameConstants.SubConstants)}.{nameof(GameConstants.SubConstants.HeaderLength)} + contentLength; // Skip marker"); } if (loqui.TargetObjectGeneration != null) { if (loqui.SetterInterfaceType == LoquiInterfaceType.IGetter) { return; } if (loqui.Singleton) { using (var args = new ArgsWrapper(fg, $"{Loqui.Generation.Utility.Await(this.IsAsync(typeGen, read: true))}{itemAccessor}.{this.Module.CopyInFromPrefix}{ModNickname}")) { args.Add($"frame: {frameAccessor}"); args.Add($"recordTypeConverter: null"); } } else { if (NeedsHeaderProcessing(loqui)) { fg.AppendLine($"frame.Position += frame.{nameof(MutagenFrame.MetaData)}.{nameof(ParsingBundle.Constants)}.{nameof(GameConstants.SubConstants)}.{nameof(GameConstants.SubConstants.HeaderLength)}; // Skip header"); } using (var args = new ArgsWrapper(fg, $"{itemAccessor} = {loqui.TargetObjectGeneration.Namespace}.{loqui.TypeNameInternal(getter: false, internalInterface: true)}.{this.Module.CreateFromPrefix}{this.Module.ModuleNickname}")) { args.Add($"frame: {frameAccessor}"); if (data?.RecordTypeConverter != null && data.RecordTypeConverter.FromConversions.Count > 0) { args.Add($"recordTypeConverter: {objGen.RegistrationName}.{typeGen.Name}Converter"); } else if (await NeedsRecordTypeConverter(loqui)) { args.AddPassArg($"recordTypeConverter"); } } } } else { throw new NotImplementedException(); } }
public override async Task GenerateWrapperRecordTypeParse( FileGeneration fg, ObjectGeneration objGen, TypeGeneration typeGen, Accessor locationAccessor, Accessor packageAccessor, Accessor converterAccessor) { using (var args = new ArgsWrapper(fg, $"{typeGen.Name}SpecialParse")) { args.AddPassArg("stream"); args.AddPassArg("offset"); args.AddPassArg("type"); args.AddPassArg("lastParsed"); } }
public override void GenerateTypicalMakeCopy(FileGeneration fg, Accessor retAccessor, Accessor rhsAccessor, Accessor copyMaskAccessor, bool deepCopy, bool doTranslationMask) { if (this.GetObjectType() != ObjectType.Record) { base.GenerateTypicalMakeCopy(fg, retAccessor, rhsAccessor, copyMaskAccessor, deepCopy, doTranslationMask: doTranslationMask); return; } switch (this.RefType) { case LoquiRefType.Direct: using (var args = new ArgsWrapper(fg, $"{retAccessor}({this.TargetObjectGeneration.ObjectName}){rhsAccessor}.{(deepCopy ? "Deep" : null)}Copy")) { if (this.RefType == LoquiRefType.Direct) { if (!doTranslationMask) { args.Add($"copyMask: default(TranslationCrystal)"); } else if (deepCopy) { args.Add($"copyMask: {copyMaskAccessor}?.GetSubCrystal({this.IndexEnumInt})"); } else { args.Add($"copyMask: {copyMaskAccessor}.Specific"); } } args.AddPassArg($"errorMask"); } break; case LoquiRefType.Generic: if (deepCopy) { fg.AppendLine($"{retAccessor}(r.DeepCopy() as {_generic})!;"); } else { fg.AppendLine($"{retAccessor}{nameof(LoquiRegistration)}.GetCopyFunc<{_generic}, {_generic}Getter>()({rhsAccessor}, null);"); } break; case LoquiRefType.Interface: if (deepCopy) { fg.AppendLine($"{retAccessor}(r.DeepCopy() as {this.TypeNameInternal(getter: false, internalInterface: true)})!;"); } else { fg.AppendLine($"{retAccessor}{nameof(LoquiRegistration)}.GetCopyFunc<{this.TypeName()}, {this.TypeName(getter: true)}>(r.GetType(), typeof({this.TypeName(getter: true)}))({rhsAccessor}, null);"); } break; default: throw new NotImplementedException(); } }
public override async Task GenerateCopyIn( FileGeneration fg, ObjectGeneration objGen, TypeGeneration typeGen, Accessor readerAccessor, Accessor itemAccessor, Accessor errorMaskAccessor, Accessor translationMaskAccessor) { var data = typeGen.GetFieldData(); using (var args = new ArgsWrapper(fg, $"SpecialParse_{typeGen.Name}")) { args.AddPassArg("item"); args.AddPassArg("frame"); } }
public override void GenerateCopyIn( FileGeneration fg, ObjectGeneration objGen, TypeGeneration typeGen, Accessor frameAccessor, Accessor itemAccessor, Accessor errorMaskAccessor, Accessor translationMaskAccessor) { FormLinkType linkType = typeGen as FormLinkType; MaskGenerationUtility.WrapErrorFieldIndexPush(fg, () => { if (itemAccessor.IsAssignment) { using (var args = new ArgsWrapper(fg, $"{itemAccessor} = {(linkType.FormIDType == FormLinkType.FormIDTypeEnum.Normal ? "FormKey" : "RecordType")}XmlTranslation.Instance.Parse")) { args.AddPassArg("node"); args.AddPassArg("errorMask"); } } else { using (var args = new FunctionWrapper(fg, itemAccessor.Assign($"new {linkType.DirectTypeName(getter: false)}"))) { args.Add(subFg => { using (var subArgs = new FunctionWrapper(subFg, $"FormKeyXmlTranslation.Instance.Parse")) { subArgs.AddPassArg("node"); subArgs.AddPassArg("errorMask"); } }); } } }, indexAccessor: typeGen.HasIndex?typeGen.IndexEnumInt: null, errorMaskAccessor: errorMaskAccessor, doIt: typeGen.HasIndex); }
public override async Task GenerateWrite( FileGeneration fg, ObjectGeneration objGen, TypeGeneration typeGen, Accessor writerAccessor, Accessor itemAccessor, Accessor errorMaskAccessor, Accessor translationMaskAccessor, Accessor converterAccessor) { var data = typeGen.GetFieldData(); using (var args = new ArgsWrapper(fg, $"{objGen.CommonClass(LoquiInterfaceType.ISetter, CommonGenerics.Class)}.SpecialWrite_{typeGen.Name}_Internal")) { args.AddPassArg("item"); args.AddPassArg("writer"); } }
public void GenerateFill( FileGeneration fg, ObjectGeneration objGen, TypeGeneration field, Accessor frameAccessor, bool isAsync, bool useReturnValue) { var data = field.GetFieldData(); var returningParseValue = useReturnValue && data.HasTrigger; using (var args = new ArgsWrapper(fg, $"{(returningParseValue ? "return " : null)}{Loqui.Generation.Utility.Await(isAsync)}{this.Module.TranslationCreateClass(field.ObjectGen)}.FillBinary{field.Name}Custom")) { args.Add($"frame: {(data.HasTrigger ? $"{frameAccessor}.SpawnWithLength(frame.{nameof(MutagenFrame.MetaData)}.{nameof(ParsingBundle.Constants)}.{nameof(GameConstants.SubConstants)}.{nameof(GameConstants.SubConstants.HeaderLength)} + contentLength)" : frameAccessor)}"); args.AddPassArg("item"); if (returningParseValue && objGen.GetObjectType() == ObjectType.Subrecord) { args.AddPassArg("lastParsed"); } } }
public override async Task GenerateWrapperRecordTypeParse( FileGeneration fg, ObjectGeneration objGen, TypeGeneration typeGen, Accessor locationAccessor, Accessor packageAccessor, Accessor converterAccessor) { var fieldData = typeGen.GetFieldData(); var returningParseValue = fieldData.HasTrigger; using (var args = new ArgsWrapper(fg, $"{(returningParseValue ? "return " : null)}{(typeGen.Name == null ? typeGen.GetFieldData().RecordType?.ToString() : typeGen.Name)}CustomParse")) { args.Add("stream"); args.Add("offset"); if (returningParseValue && objGen.GetObjectType() == ObjectType.Subrecord) { args.AddPassArg("lastParsed"); } } }
public override void GenerateForEqualsMask(FileGeneration fg, Accessor accessor, Accessor rhsAccessor, string retAccessor) { LoquiType loqui = this.SubTypeGeneration as LoquiType; if (this.Nullable || loqui != null) { using (var args = new ArgsWrapper(fg, $"ret.{this.Name} = {nameof(GenderedItem)}.{nameof(GenderedItem.EqualityMaskHelper)}")) { args.Add($"lhs: {accessor}"); args.Add($"rhs: {rhsAccessor}"); if (loqui == null) { args.Add($"maskGetter: (l, r, i) => EqualityComparer<{this.SubTypeGeneration.TypeName(getter: true, needsCovariance: true)}{this.SubTypeGeneration.NullChar}>.Default.Equals(l, r)"); } else { if (this.ItemNullable) { args.Add($"maskGetter: (l, r, i) => EqualsMaskHelper.EqualsHelper(l, r, (loqLhs, loqRhs, incl) => loqLhs.GetEqualsMask(loqRhs, incl), i)"); } else { args.Add("maskGetter: (l, r, i) => l.GetEqualsMask(r, i)"); } } args.AddPassArg("include"); } } else { using (var args = new ArgsWrapper(fg, $"ret.{this.Name} = new GenderedItem<bool>")) { args.Add($"male: {this.SubTypeGeneration.GenerateEqualsSnippet($"{accessor}.Male", $"{rhsAccessor}.Male")}"); args.Add($"female: {this.SubTypeGeneration.GenerateEqualsSnippet($"{accessor}.Female", $"{rhsAccessor}.Female")}"); } } }
public override void GenerateForAny(FileGeneration fg, TypeGeneration field, Accessor accessor, bool nullCheck, bool indexed) { if (!field.IntegrateField) { return; } GenderedType gendered = field as GenderedType; var isLoqui = gendered.SubTypeGeneration is LoquiType; if (field.Nullable || isLoqui) { using (var args = new ArgsWrapper(fg, $"if ({nameof(GenderedItem)}.{(isLoqui ? nameof(GenderedItem.AnyMask) : nameof(GenderedItem.Any))}", suffixLine: ") return true")) { args.Add($"{accessor}"); args.AddPassArg("eval"); } } else { fg.AppendLine($"if (eval({accessor}{(indexed ? ".Value" : null)}.Male) || eval({accessor}{(indexed ? ".Value" : null)}.Female)) return true;"); } }
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(); } } }
private async Task LoquiTypeHandler( FileGeneration fg, ObjectGeneration obj, Accessor loquiAccessor, LoquiType loquiType, Action <ArgsWrapper> addGetOrAddArg, string generic, bool checkType, bool includeSelf = true) { // ToDo // Quick hack. Real solution should use reflection to investigate the interface if (loquiType.RefType == LoquiType.LoquiRefType.Interface) { if (checkType) { fg.AppendLine($"if (type.IsAssignableFrom({loquiAccessor}.GetType()))"); } using (new BraceWrapper(fg, doIt: checkType)) { using (var args = new ArgsWrapper(fg, $"yield return new ModContext<{obj.GetObjectData().GameCategory.Value.ModInterface(getter: false)}, IMajorRecordCommon, IMajorRecordCommonGetter>")) { args.Add($"modKey: {(obj.GetObjectType() == ObjectType.Mod ? "obj.ModKey" : "modKey")}"); args.Add($"record: {loquiAccessor}"); args.Add($"parent: curContext"); addGetOrAddArg(args); } } return; } if (includeSelf && loquiType.TargetObjectGeneration != null && await loquiType.TargetObjectGeneration.IsMajorRecord()) { if (checkType) { fg.AppendLine($"if (type.IsAssignableFrom({loquiAccessor}.GetType()))"); } using (new BraceWrapper(fg, doIt: checkType)) { using (var args = new ArgsWrapper(fg, $"yield return new ModContext<{obj.GetObjectData().GameCategory.Value.ModInterface(getter: false)}, IMajorRecordCommon, IMajorRecordCommonGetter>")) { args.Add($"modKey: {(obj.GetObjectType() == ObjectType.Mod ? "obj.ModKey" : "modKey")}"); args.Add($"record: {loquiAccessor}"); args.Add($"parent: curContext"); addGetOrAddArg(args); } } } if (await MajorRecordModule.HasMajorRecords(loquiType, includeBaseClass: true, includeSelf: false) == Case.No) { return; } if (obj.IsListGroup()) { return; } if (obj.IsTopLevelGroup()) { fg.AppendLine($"foreach (var item in {loquiAccessor}.EnumerateMajorRecords({(generic == null ? null : "type, throwIfUnknown: false")}))"); using (new BraceWrapper(fg)) { using (var args = new ArgsWrapper(fg, $"yield return new ModContext<{obj.GetObjectData().GameCategory.Value.ModInterface(getter: false)}, IMajorRecordCommon, IMajorRecordCommonGetter>")) { args.Add($"modKey: {(obj.GetObjectType() == ObjectType.Mod ? "obj.ModKey" : "modKey")}"); args.Add("record: item"); args.Add($"getOrAddAsOverride: (m, r) => m.{loquiType.Name}.GetOrAddAsOverride(({loquiType.GetGroupTarget().Interface(getter: true, internalInterface: true)})r)"); } } } else { using (var args = new ArgsWrapper(fg, $"foreach (var item in {loquiType.TargetObjectGeneration.CommonClassInstance(loquiAccessor, LoquiInterfaceType.IGetter, CommonGenerics.Class)}.EnumerateMajorRecordContexts", suffixLine: ")") { SemiColon = false }) { args.Add($"obj: {loquiAccessor}"); args.AddPassArg("linkCache"); args.AddPassArg("type"); args.Add($"modKey: {(obj.GetObjectType() == ObjectType.Mod ? "obj.ModKey" : "modKey")}"); args.Add($"parent: {(obj.GetObjectType() == ObjectType.Mod ? "null" : "curContext")}"); args.Add("throwIfUnknown: false"); addGetOrAddArg(args); } using (new BraceWrapper(fg)) { fg.AppendLine("yield return item;"); } } }
public override async Task GenerateInCommonMixin(ObjectGeneration obj, FileGeneration fg) { if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No) { return; } fg.AppendLine("[DebuggerStepThrough]"); using (var args = new FunctionWrapper(fg, $"public static void Remove{obj.GetGenericTypes(MaskType.Normal)}")) { args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics)); args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj"); args.Add($"{nameof(FormKey)} key"); } using (new BraceWrapper(fg)) { fg.AppendLine($"var keys = new HashSet<{nameof(FormKey)}>();"); fg.AppendLine("keys.Add(key);"); using (var args = new ArgsWrapper(fg, $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove")) { args.AddPassArg("obj"); args.AddPassArg("keys"); } } fg.AppendLine(); if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No) { return; } fg.AppendLine("[DebuggerStepThrough]"); using (var args = new FunctionWrapper(fg, $"public static void Remove{obj.GetGenericTypes(MaskType.Normal)}")) { args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics)); args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj"); args.Add($"IEnumerable<{nameof(FormKey)}> keys"); } using (new BraceWrapper(fg)) { using (var args = new ArgsWrapper(fg, $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove")) { args.AddPassArg("obj"); args.Add("keys: keys.ToHashSet()"); } } fg.AppendLine(); if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No) { return; } fg.AppendLine("[DebuggerStepThrough]"); using (var args = new FunctionWrapper(fg, $"public static void Remove{obj.GetGenericTypes(MaskType.Normal)}")) { args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics)); args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj"); args.Add($"HashSet<{nameof(FormKey)}> keys"); } using (new BraceWrapper(fg)) { using (var args = new ArgsWrapper(fg, $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove")) { args.AddPassArg("obj"); args.AddPassArg("keys"); } } fg.AppendLine(); fg.AppendLine("[DebuggerStepThrough]"); using (var args = new FunctionWrapper(fg, $"public static void Remove{obj.GetGenericTypes(MaskType.Normal)}")) { args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics)); args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj"); args.Add($"{nameof(FormKey)} key"); args.Add($"{nameof(Type)} type"); args.Add($"bool throwIfUnknown = true"); } using (new BraceWrapper(fg)) { fg.AppendLine($"var keys = new HashSet<{nameof(FormKey)}>();"); fg.AppendLine("keys.Add(key);"); using (var args = new ArgsWrapper(fg, $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove")) { args.AddPassArg("obj"); args.AddPassArg("keys"); args.AddPassArg("type"); args.AddPassArg("throwIfUnknown"); } } fg.AppendLine(); if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No) { return; } fg.AppendLine("[DebuggerStepThrough]"); using (var args = new FunctionWrapper(fg, $"public static void Remove{obj.GetGenericTypes(MaskType.Normal)}")) { args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics)); args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj"); args.Add($"IEnumerable<{nameof(FormKey)}> keys"); args.Add($"{nameof(Type)} type"); args.Add($"bool throwIfUnknown = true"); } using (new BraceWrapper(fg)) { using (var args = new ArgsWrapper(fg, $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove")) { args.AddPassArg("obj"); args.Add("keys: keys.ToHashSet()"); args.AddPassArg("type"); args.AddPassArg("throwIfUnknown"); } } fg.AppendLine(); if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No) { return; } fg.AppendLine("[DebuggerStepThrough]"); using (var args = new FunctionWrapper(fg, $"public static void Remove{obj.GetGenericTypes(MaskType.Normal)}")) { args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics)); args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj"); args.Add($"HashSet<{nameof(FormKey)}> keys"); args.Add($"{nameof(Type)} type"); args.Add($"bool throwIfUnknown = true"); } using (new BraceWrapper(fg)) { using (var args = new ArgsWrapper(fg, $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove")) { args.AddPassArg("obj"); args.AddPassArg("keys"); args.AddPassArg("type"); args.AddPassArg("throwIfUnknown"); } } fg.AppendLine(); fg.AppendLine("[DebuggerStepThrough]"); using (var args = new FunctionWrapper(fg, $"public static void Remove{obj.GetGenericTypes(MaskType.Normal, "TMajor")}")) { args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics)); args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj"); args.Add($"TMajor record"); args.Add($"bool throwIfUnknown = true"); args.Wheres.Add($"where TMajor : {nameof(IMajorRecordGetter)}"); } using (new BraceWrapper(fg)) { fg.AppendLine($"var keys = new HashSet<{nameof(FormKey)}>();"); fg.AppendLine("keys.Add(record.FormKey);"); using (var args = new ArgsWrapper(fg, $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove")) { args.AddPassArg("obj"); args.AddPassArg("keys"); args.Add("type: typeof(TMajor)"); args.AddPassArg("throwIfUnknown"); } } fg.AppendLine(); if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No) { return; } fg.AppendLine("[DebuggerStepThrough]"); using (var args = new FunctionWrapper(fg, $"public static void Remove{obj.GetGenericTypes(MaskType.Normal, "TMajor")}")) { args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics)); args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj"); args.Add($"IEnumerable<TMajor> records"); args.Add($"bool throwIfUnknown = true"); args.Wheres.Add($"where TMajor : {nameof(IMajorRecordGetter)}"); } using (new BraceWrapper(fg)) { using (var args = new ArgsWrapper(fg, $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove")) { args.AddPassArg("obj"); args.Add("keys: records.Select(m => m.FormKey).ToHashSet()"); args.Add("type: typeof(TMajor)"); args.AddPassArg("throwIfUnknown"); } } fg.AppendLine(); fg.AppendLine("[DebuggerStepThrough]"); using (var args = new FunctionWrapper(fg, $"public static void Remove{obj.GetGenericTypes(MaskType.Normal, "TMajor")}")) { args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics)); args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj"); args.Add($"{nameof(FormKey)} key"); args.Add($"bool throwIfUnknown = true"); args.Wheres.Add($"where TMajor : {nameof(IMajorRecordGetter)}"); } using (new BraceWrapper(fg)) { fg.AppendLine($"var keys = new HashSet<{nameof(FormKey)}>();"); fg.AppendLine("keys.Add(key);"); using (var args = new ArgsWrapper(fg, $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove")) { args.AddPassArg("obj"); args.AddPassArg("keys"); args.Add("type: typeof(TMajor)"); args.AddPassArg("throwIfUnknown"); } } fg.AppendLine(); if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No) { return; } fg.AppendLine("[DebuggerStepThrough]"); using (var args = new FunctionWrapper(fg, $"public static void Remove{obj.GetGenericTypes(MaskType.Normal, "TMajor")}")) { args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics)); args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj"); args.Add($"IEnumerable<{nameof(FormKey)}> keys"); args.Add($"bool throwIfUnknown = true"); args.Wheres.Add($"where TMajor : {nameof(IMajorRecordGetter)}"); } using (new BraceWrapper(fg)) { using (var args = new ArgsWrapper(fg, $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove")) { args.AddPassArg("obj"); args.Add("keys: keys.ToHashSet()"); args.Add("type: typeof(TMajor)"); args.AddPassArg("throwIfUnknown"); } } fg.AppendLine(); if (await MajorRecordModule.HasMajorRecordsInTree(obj, includeBaseClass: false) == Case.No) { return; } fg.AppendLine("[DebuggerStepThrough]"); using (var args = new FunctionWrapper(fg, $"public static void Remove{obj.GetGenericTypes(MaskType.Normal, "TMajor")}")) { args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.ISetter, obj.Generics)); args.Add($"this {obj.Interface(getter: false, internalInterface: true)} obj"); args.Add($"HashSet<{nameof(FormKey)}> keys"); args.Add($"bool throwIfUnknown = true"); args.Wheres.Add($"where TMajor : {nameof(IMajorRecordGetter)}"); } using (new BraceWrapper(fg)) { using (var args = new ArgsWrapper(fg, $"{obj.CommonClassInstance("obj", LoquiInterfaceType.ISetter, CommonGenerics.Class)}.Remove")) { args.AddPassArg("obj"); args.AddPassArg("keys"); args.Add("type: typeof(TMajor)"); args.AddPassArg("throwIfUnknown"); } } fg.AppendLine(); }
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 GenerateCopyIn( FileGeneration fg, ObjectGeneration objGen, TypeGeneration typeGen, Accessor nodeAccessor, Accessor itemAccessor, Accessor errorMaskAccessor, Accessor translationMaskAccessor) { var dict = typeGen as DictType; var data = dict.GetFieldData(); var subData = dict.ValueTypeGen.GetFieldData(); if (!this.Module.TryGetTypeGeneration(dict.ValueTypeGen.GetType(), out var subTransl)) { throw new ArgumentException("Unsupported type generator: " + dict.ValueTypeGen); } var isAsync = subTransl.IsAsync(dict.ValueTypeGen, read: true); var binaryType = GetDictType(dict); if (data.MarkerType.HasValue) { fg.AppendLine("frame.Position += Constants.SUBRECORD_LENGTH + long; // Skip marker"); } else if (binaryType == DictBinaryType.Trigger) { fg.AppendLine("frame.Position += Constants.SUBRECORD_LENGTH;"); } var term = binaryType == DictBinaryType.EnumMap ? "Dict" : "List"; using (var args = new ArgsWrapper(fg, $"{Loqui.Generation.Utility.Await(isAsync)}{this.Namespace}{term}{(isAsync ? "Async" : null)}BinaryTranslation<{dict.ValueTypeGen.TypeName(getter: false)}>.Instance.Parse{(binaryType == DictBinaryType.EnumMap ? $"<{dict.KeyTypeGen.TypeName(false)}>" : null)}", suffixLine: Loqui.Generation.Utility.ConfigAwait(isAsync))) { switch (binaryType) { case DictBinaryType.SubTrigger: args.AddPassArg($"frame"); args.Add($"triggeringRecord: {subData.TriggeringRecordSetAccessor}"); break; case DictBinaryType.Trigger: args.Add($"frame: frame.Spawn(long)"); break; case DictBinaryType.EnumMap: args.AddPassArg($"frame"); break; default: throw new NotImplementedException(); } args.Add($"item: {itemAccessor}"); var subGenTypes = subData.GenerationTypes.ToList(); var subGen = this.Module.GetTypeGeneration(dict.ValueTypeGen.GetType()); if (subGenTypes.Count <= 1 && subTransl.AllowDirectParse(objGen, typeGen, squashedRepeatedList: false)) { args.Add($"transl: {subTransl.GetTranslatorInstance(dict.ValueTypeGen, getter: false)}.Parse"); } else if (subGenTypes.Count > 1) { args.Add((gen) => { gen.AppendLine($"transl: (MutagenFrame r, RecordType header{(isAsync ? null : $", out {dict.ValueTypeGen.TypeName(getter: false)} dictSubItem")}) =>"); using (new BraceWrapper(gen)) { gen.AppendLine("switch (header.Type)"); using (new BraceWrapper(gen)) { foreach (var item in subGenTypes) { foreach (var trigger in item.Key) { gen.AppendLine($"case \"{trigger.Type}\":"); } LoquiType targetLoqui = dict.ValueTypeGen as LoquiType; LoquiType specificLoqui = item.Value as LoquiType; using (new DepthWrapper(gen)) { subGen.GenerateCopyInRet( fg: gen, objGen: objGen, targetGen: dict.ValueTypeGen, typeGen: item.Value, readerAccessor: "r", retAccessor: "return ", outItemAccessor: new Accessor("dictSubItem"), translationAccessor: "dictTranslMask", asyncMode: AsyncMode.Off, errorMaskAccessor: null, converterAccessor: null, inline: true); } } gen.AppendLine("default:"); using (new DepthWrapper(gen)) { gen.AppendLine("throw new NotImplementedException();"); } } } }); } else { args.Add((gen) => { LoquiType targetLoqui = dict.ValueTypeGen as LoquiType; subGen.GenerateCopyInRet( fg: gen, objGen: objGen, targetGen: dict.ValueTypeGen, typeGen: targetLoqui, readerAccessor: "r", retAccessor: "transl: ", outItemAccessor: new Accessor("dictSubItem"), translationAccessor: "dictTranslMask", asyncMode: AsyncMode.Off, errorMaskAccessor: null, converterAccessor: null, inline: true); }); } } }
async Task ApplyRemovalLines( TypeGeneration field, FileGeneration fieldGen, Accessor accessor, bool removeSelf, ObjectGeneration obj = null, HashSet <ObjectGeneration> blackList = null) { if (field is GroupType group) { if (blackList?.Contains(group.GetGroupTarget()) ?? false) { return; } using (var args = new ArgsWrapper(fieldGen, $"obj.{field.Name}.Remove")) { args.AddPassArg("type"); args.AddPassArg("keys"); } } else if (field is LoquiType loqui) { if (blackList?.Contains(loqui.TargetObjectGeneration) ?? false) { return; } var fieldAccessor = loqui.Nullable ? $"{obj?.ObjectName}{loqui.Name}item" : $"{accessor}.{loqui.Name}"; if (loqui.TargetObjectGeneration.IsListGroup()) { // List groups using (var args = new ArgsWrapper(fieldGen, $"obj.{field.Name}.Remove")) { args.AddPassArg("type"); args.AddPassArg("keys"); } return; } var subFg = new FileGeneration(); subFg.AppendLine($"{fieldAccessor}.Remove(keys, type, throwIfUnknown);"); if (loqui.Singleton || !loqui.Nullable) { fieldGen.AppendLines(subFg); } else { using (new BraceWrapper(fieldGen)) { fieldGen.AppendLine($"if ({accessor}.{loqui.Name} is {{}} {fieldAccessor})"); using (new BraceWrapper(fieldGen)) { fieldGen.AppendLines(subFg); } } } } else if (field is ContainerType cont) { if (!(cont.SubTypeGeneration is LoquiType contLoqui)) { return; } if (contLoqui.RefType == LoquiType.LoquiRefType.Generic) { fieldGen.AppendLine($"foreach (var item in obj.{field.Name})"); using (new BraceWrapper(fieldGen)) { fieldGen.AppendLine($"item.Remove(keys, type, throwIfUnknown: false);"); } fieldGen.AppendLine($"obj.{field.Name}.RemoveWhere(i => i.{contLoqui.TargetObjectGeneration.Fields.FirstOrDefault(f => f is ContainerType).Name}.Count == 0);"); } else { var isMajorRecord = contLoqui.TargetObjectGeneration != null && await contLoqui.TargetObjectGeneration.IsMajorRecord(); if (isMajorRecord || await MajorRecordModule.HasMajorRecords(contLoqui, includeBaseClass: true) != Case.No) { if (removeSelf) { fieldGen.AppendLine($"obj.{field.Name}.RemoveWhere(i => keys.Contains(i.FormKey));"); } switch (await MajorRecordModule.HasMajorRecords(contLoqui, includeBaseClass: true, includeSelf: false)) { case Case.Yes: case Case.Maybe: fieldGen.AppendLine($"foreach (var subItem in {accessor}.{field.Name}{(field.Nullable ? ".EmptyIfNull()" : null)})"); using (new BraceWrapper(fieldGen)) { fieldGen.AppendLine("subItem.Remove(keys, type, throwIfUnknown: false);"); } break; case Case.No: default: break; } } } if (contLoqui.TargetObjectGeneration != null && contLoqui.TargetObjectGeneration.IsListGroup() && (await contLoqui.TargetObjectGeneration.GetGroupLoquiType()).TargetObjectGeneration == obj) { fieldGen.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) { return; } if (!(dict.ValueTypeGen is LoquiType dictLoqui)) { return; } if (dictLoqui.RefType == LoquiType.LoquiRefType.Generic) { fieldGen.AppendLine($"if (type.IsAssignableFrom(typeof({dictLoqui.GenericDef.Name})))"); using (new BraceWrapper(fieldGen)) { fieldGen.AppendLine($"obj.RecordCache.Remove(keys);"); } fieldGen.AppendLine($"foreach (var item in obj.{field.Name}.Items)"); using (new BraceWrapper(fieldGen)) { fieldGen.AppendLine($"item.Remove(keys, type, throwIfUnknown: false);"); } } else { 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: fieldGen.AppendLine($"foreach (var subItem in {accessor}.{field.Name}.Items)"); using (new BraceWrapper(fieldGen)) { throw new NotImplementedException(); } break; case Case.Maybe: fieldGen.AppendLine($"foreach (var subItem in {accessor}.{field.Name}.Items.WhereCastable<{dictLoqui.TypeName(getter: false)}, {nameof(IMajorRecordEnumerable)}>())"); using (new BraceWrapper(fieldGen)) { throw new NotImplementedException(); } break; case Case.No: default: break; } } } } }
public override async Task GenerateCopyIn( FileGeneration fg, ObjectGeneration objGen, TypeGeneration typeGen, Accessor readerAccessor, Accessor itemAccessor, Accessor errorMaskAccessor, Accessor translationAccessor) { GenderedType gender = typeGen as GenderedType; var data = typeGen.GetFieldData(); if (!this.Module.TryGetTypeGeneration(gender.SubTypeGeneration.GetType(), out var subTransl)) { throw new ArgumentException("Unsupported type generator: " + gender.SubTypeGeneration); } if (data.RecordType.HasValue) { fg.AppendLine($"{readerAccessor}.Position += {readerAccessor}.{nameof(MutagenBinaryReadStream.MetaData)}.{nameof(ParsingBundle.Constants)}.{nameof(GameConstants.SubConstants)}.{nameof(RecordHeaderConstants.HeaderLength)};"); } else if (data.MarkerType.HasValue && !gender.MarkerPerGender) { fg.AppendLine($"{readerAccessor}.Position += {readerAccessor}.{nameof(MutagenBinaryReadStream.MetaData)}.{nameof(ParsingBundle.Constants)}.{nameof(GameConstants.SubConstants)}.{nameof(RecordHeaderConstants.HeaderLength)} + contentLength; // Skip marker"); } bool notNull = gender.ItemNullable && !gender.SubTypeGeneration.IsNullable; using (var args = new ArgsWrapper(fg, $"{itemAccessor} = {this.NamespacePrefix}GenderedItemBinaryTranslation.Parse{(gender.MarkerPerGender ? "MarkerPerItem" : null)}<{gender.SubTypeGeneration.TypeName(getter: false, needsCovariance: true)}>")) { args.AddPassArg($"frame"); if (gender.MaleMarker.HasValue) { args.Add($"maleMarker: {objGen.RecordTypeHeaderName(gender.MaleMarker.Value)}"); args.Add($"femaleMarker: {objGen.RecordTypeHeaderName(gender.FemaleMarker.Value)}"); } if (data.MarkerType.HasValue && gender.MarkerPerGender) { args.Add($"marker: {objGen.RecordTypeHeaderName(data.MarkerType.Value)}"); } var subData = gender.SubTypeGeneration.GetFieldData(); if (subData.RecordType.HasValue && !(gender.SubTypeGeneration is LoquiType)) { args.Add($"contentMarker: {objGen.RecordTypeHeaderName(subData.RecordType.Value)}"); } LoquiType loqui = gender.SubTypeGeneration as LoquiType; if (loqui != null) { if (subData?.RecordTypeConverter != null && subData.RecordTypeConverter.FromConversions.Count > 0) { args.Add($"parseParams: {objGen.RegistrationName}.{typeGen.Name}Converter"); } } if (gender.FemaleConversions != null) { args.Add($"femaleRecordConverter: {objGen.RegistrationName}.{typeGen.Name}FemaleConverter"); } if (gender.MaleConversions != null) { args.Add($"maleRecordConverter: {objGen.RegistrationName}.{typeGen.Name}MaleConverter"); } bool needsRecordConv = gender.SubTypeGeneration.NeedsRecordConverter(); if (subTransl.AllowDirectParse(objGen, gender.SubTypeGeneration, false)) { if (loqui != null) { args.Add($"transl: {loqui.ObjectTypeName}{loqui.GenericTypes(getter: false)}.TryCreateFromBinary"); } else { args.Add($"transl: {subTransl.GetTranslatorInstance(gender.SubTypeGeneration, getter: false)}.Parse"); if (gender.ItemNullable) { args.Add($"skipMarker: false"); } } } else { args.Add(gen => { gen.AppendLine($"transl: (MutagenFrame r, out {gender.SubTypeGeneration.TypeName(getter: false, needsCovariance: true)} genSubItem{(needsRecordConv ? $", {nameof(RecordTypeConverter)}? conv" : null)}) =>"); using (new BraceWrapper(gen)) { subTransl.GenerateCopyInRet( fg: gen, objGen: objGen, targetGen: gender.SubTypeGeneration, typeGen: gender.SubTypeGeneration, readerAccessor: "r", translationAccessor: null, retAccessor: "return ", outItemAccessor: new Accessor("genSubItem"), asyncMode: AsyncMode.Off, errorMaskAccessor: "listErrMask", converterAccessor: "conv", inline: false); } if (gender.ItemNullable) { args.Add($"skipMarker: false"); } }); } if (notNull) { args.Add($"fallback: {gender.SubTypeGeneration.GetDefault(getter: false)}"); } } }
public override async Task GenerateWrapperRecordTypeParse( FileGeneration fg, ObjectGeneration objGen, TypeGeneration typeGen, Accessor locationAccessor, Accessor packageAccessor, Accessor converterAccessor) { LoquiType loqui = typeGen as LoquiType; var data = loqui.GetFieldData(); switch (data.BinaryOverlayFallback) { case BinaryGenerationType.Normal: break; case BinaryGenerationType.NoGeneration: return; case BinaryGenerationType.Custom: using (var args = new ArgsWrapper(fg, $"{typeGen.Name}CustomParse")) { args.Add("stream"); args.Add("finalPos"); args.Add("offset"); } return; default: throw new NotImplementedException(); } string accessor; if (loqui.Singleton || !loqui.Nullable) { accessor = $"_{typeGen.Name}"; } else { accessor = typeGen.Name; } if (data.MarkerType.HasValue) { fg.AppendLine($"stream.Position += {packageAccessor}.{nameof(BinaryOverlayFactoryPackage.MetaData)}.{nameof(ParsingBundle.Constants)}.SubConstants.HeaderLength; // Skip marker"); } if (!loqui.TargetObjectGeneration.IsTypelessStruct() && (loqui.GetFieldData()?.HasTrigger ?? false)) { fg.AppendLine($"_{typeGen.Name}Location = new {GetLocationObjectString(objGen)}({locationAccessor}, finalPos);"); var severalSubTypes = data.GenerationTypes .Select(i => i.Value) .WhereCastable <TypeGeneration, LoquiType>() .Where(loqui => !loqui?.TargetObjectGeneration?.Abstract ?? true) .CountGreaterThan(1); if (severalSubTypes) { fg.AppendLine($"_{typeGen.Name}Type = type;"); } } else { if (NeedsHeaderProcessing(loqui)) { fg.AppendLine($"stream.Position += _package.{nameof(BinaryOverlayFactoryPackage.MetaData)}.{nameof(ParsingBundle.Constants)}.SubConstants.HeaderLength;"); } using (var args = new ArgsWrapper(fg, $"this.{accessor} = {this.Module.BinaryOverlayClassName(loqui)}.{loqui.TargetObjectGeneration.Name}Factory")) { args.Add($"stream: stream"); args.Add($"package: {packageAccessor}"); if (loqui.TargetObjectGeneration.IsVariableLengthStruct()) { args.AddPassArg($"finalPos"); } args.Add($"recordTypeConverter: {converterAccessor}"); } } }
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(); }
async Task ApplyIterationLines( ObjectGeneration obj, TypeGeneration field, FileGeneration fieldGen, Accessor accessor, bool getter, bool hasTarget = false, HashSet <ObjectGeneration> blackList = null, bool includeSelf = true) { if (field is GroupType group) { if (blackList?.Contains(group.GetGroupTarget()) ?? false) { return; } if (!hasTarget) { fieldGen.AppendLine($"foreach (var item in obj.{field.Name}.EnumerateMajorRecords(type, throwIfUnknown: throwIfUnknown))"); using (new BraceWrapper(fieldGen)) { using (var args = new ArgsWrapper(fieldGen, $"yield return new ModContext<{obj.Interface(getter: false)}, IMajorRecordCommon, IMajorRecordCommonGetter>")) { args.Add("modKey: obj.ModKey"); args.Add("record: item"); args.Add($"getter: (m, r) => m.{group.Name}.GetOrAddAsOverride(({group.GetGroupTarget().Interface(getter: true, internalInterface: true)})r)"); } } } else { fieldGen.AppendLine($"foreach (var groupItem in obj.{field.Name})"); using (new BraceWrapper(fieldGen)) { fieldGen.AppendLine($"foreach (var item in {group.GetGroupTarget().CommonClass(LoquiInterfaceType.IGetter, CommonGenerics.Class)}.Instance.EnumerateMajorRecordContexts(groupItem, linkCache, type, {(obj.GetObjectType() == ObjectType.Mod ? "obj.ModKey" : "modKey")}, {(obj.GetObjectType() == ObjectType.Mod ? "parent: null" : "curContext")}, throwIfUnknown: throwIfUnknown, getter: (m, r) => m.{field.Name}.GetOrAddAsOverride(linkCache.Resolve<{group.GetGroupTarget().Interface(getter: true, internalInterface: true)}>(r.FormKey))))"); using (new BraceWrapper(fieldGen)) { fieldGen.AppendLine("yield return item;"); } } } } else if (field is LoquiType loqui) { if (blackList?.Contains(loqui.TargetObjectGeneration) ?? false) { return; } var fieldAccessor = loqui.Nullable ? $"{obj.ObjectName}{loqui.Name}item" : $"{accessor}.{loqui.Name}"; if (loqui.TargetObjectGeneration.IsListGroup()) { // List groups fieldGen.AppendLine($"foreach (var item in obj.{field.Name}.EnumerateMajorRecordContexts(linkCache, type, {(obj.GetObjectType() == ObjectType.Mod ? "obj.ModKey" : "modKey")}, {(obj.GetObjectType() == ObjectType.Mod ? "parent: null" : "curContext")}, throwIfUnknown: throwIfUnknown))"); using (new BraceWrapper(fieldGen)) { fieldGen.AppendLine("yield return item;"); } return; } var subFg = new FileGeneration(); await LoquiTypeHandler( subFg, obj, fieldAccessor, loqui, generic : "TMajor", checkType : false, includeSelf : includeSelf, addGetOrAddArg : (args) => { args.Add(subFg => { subFg.AppendLine($"getter: (m, r) =>"); using (new BraceWrapper(subFg)) { subFg.AppendLine($"var baseRec = getter(m, linkCache.Resolve<{obj.Interface(getter: true)}>(obj.FormKey));"); subFg.AppendLine($"if (baseRec.{loqui.Name} != null) return baseRec.{loqui.Name};"); subFg.AppendLine($"var copy = ({loqui.TypeName()})(({loqui.Interface(getter: true)})r).DeepCopy(ModContextExt.{loqui.TargetObjectGeneration.Name}CopyMask);"); subFg.AppendLine($"baseRec.{loqui.Name} = copy;"); subFg.AppendLine($"return copy;"); } }); }); if (subFg.Count == 0) { return; } if (loqui.Singleton || !loqui.Nullable) { fieldGen.AppendLines(subFg); } else { using (new BraceWrapper(fieldGen)) { fieldGen.AppendLine($"if ({accessor}.{loqui.Name}.TryGet(out var {fieldAccessor}))"); using (new BraceWrapper(fieldGen)) { fieldGen.AppendLines(subFg); } } } } else if (field is ContainerType cont) { if (!(cont.SubTypeGeneration is LoquiType contLoqui)) { return; } if (contLoqui.RefType == LoquiType.LoquiRefType.Generic) { fieldGen.AppendLine($"foreach (var item in obj.{field.Name})"); using (new BraceWrapper(fieldGen)) { if (await contLoqui.TargetObjectGeneration.IsMajorRecord()) { fieldGen.AppendLine($"if (type.IsAssignableFrom(typeof({contLoqui.GenericDef.Name})))"); using (new BraceWrapper(fieldGen)) { fieldGen.AppendLine($"yield return ({nameof(IMajorRecordCommonGetter)})item;"); } } fieldGen.AppendLine($"foreach (var subItem in item.EnumerateMajorRecords(type, throwIfUnknown: throwIfUnknown))"); using (new BraceWrapper(fieldGen)) { fieldGen.AppendLine($"yield return subItem;"); } } } else if (contLoqui.TargetObjectGeneration?.IsListGroup() ?? false) { using (var args = new ArgsWrapper(fieldGen, $"foreach (var item in {accessor}.{field.Name}.EnumerateMajorRecordContexts", suffixLine: ")") { SemiColon = false }) { args.AddPassArg("type"); args.Add($"modKey: {(obj.GetObjectType() == ObjectType.Mod ? "obj.ModKey" : "modKey")}"); args.Add($"parent: {(obj.GetObjectType() == ObjectType.Mod ? "null" : "curContext")}"); args.AddPassArg("linkCache"); args.Add("throwIfUnknown: false"); args.Add("worldspace: obj"); args.AddPassArg("getter"); } using (new BraceWrapper(fieldGen)) { fieldGen.AppendLine("yield return item;"); } } else { 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: fieldGen.AppendLine($"foreach (var subItem in {accessor}.{field.Name}{(field.Nullable ? ".EmptyIfNull()" : null)})"); using (new BraceWrapper(fieldGen)) { await LoquiTypeHandler( fieldGen, obj, $"subItem", contLoqui, generic : "TMajor", checkType : true, addGetOrAddArg : (args) => { args.Add(subFg => { subFg.AppendLine($"getter: (m, r) =>"); using (new BraceWrapper(subFg)) { subFg.AppendLine($"var copy = ({contLoqui.TypeName()})(({contLoqui.Interface(getter: true)})r).DeepCopy();"); subFg.AppendLine($"getter(m, linkCache.Resolve<{obj.Interface(getter: true)}>(obj.FormKey)).{cont.Name}.Add(copy);"); subFg.AppendLine($"return copy;"); } }); }); } break; case Case.Maybe: throw new NotImplementedException(); case Case.No: default: break; } } } } else if (field is DictType dict) { throw new NotImplementedException(); } }
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(); }
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(); }
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(); }
private void GenerateWriteParallel(ObjectGeneration obj, FileGeneration fg) { LoquiType groupInstance = null; LoquiType listGroupInstance = null; var objData = obj.GetObjectData(); fg.AppendLine("const int CutCount = 100;"); using (var args = new FunctionWrapper(fg, "public static void WriteParallel")) { args.Add($"{obj.Interface(getter: true, internalInterface: false)} item"); args.Add($"Stream stream"); args.Add($"{nameof(BinaryWriteParameters)} param"); args.Add($"ModKey modKey"); } using (new BraceWrapper(fg)) { string gameConstantsStr; if (objData.GameReleaseOptions == null) { gameConstantsStr = $"{nameof(GameConstants)}.{obj.GetObjectData().GameCategory}"; } else { fg.AppendLine($"var gameConstants = {nameof(GameConstants)}.Get(item.{ReleaseEnumName(obj)}.ToGameRelease());"); gameConstantsStr = $"gameConstants"; } fg.AppendLine($"var bundle = new {nameof(WritingBundle)}({gameConstantsStr});"); fg.AppendLine($"var writer = new MutagenWriter(stream, bundle);"); using (var args = new ArgsWrapper(fg, $"{nameof(ModHeaderWriteLogic)}.{nameof(ModHeaderWriteLogic.WriteHeader)}")) { args.AddPassArg("param"); args.AddPassArg("writer"); args.Add("mod: item"); args.Add("modHeader: item.ModHeader.DeepCopy()"); args.AddPassArg("modKey"); } int groupCount = obj.IterateFields() .Select(f => f as LoquiType) .Where(l => l != null) .Where(l => l.TargetObjectGeneration?.GetObjectData().ObjectType == ObjectType.Group) .Count(); fg.AppendLine($"Stream[] outputStreams = new Stream[{groupCount}];"); fg.AppendLine($"List<Action> toDo = new List<Action>();"); int i = 0; foreach (var field in obj.IterateFields()) { if (!(field is LoquiType loqui)) { continue; } if (loqui.TargetObjectGeneration?.GetObjectData().ObjectType != ObjectType.Group) { continue; } if (loqui.TargetObjectGeneration.Name == "ListGroup") { listGroupInstance = loqui; } else { groupInstance = loqui; } if (loqui.GetGroupTarget().GetObjectData().CustomBinaryEnd == CustomEnd.Off && loqui.TargetObjectGeneration.Name != "ListGroup") { fg.AppendLine($"toDo.Add(() => WriteGroupParallel(item.{field.Name}, writer.MetaData.MasterReferences!, {i}{(objData.GameReleaseOptions == null ? null : ", gameConstants")}, outputStreams{(objData.UsesStringFiles ? ", param.StringsWriter" : null)}));"); } else { fg.AppendLine($"toDo.Add(() => Write{field.Name}Parallel(item.{field.Name}, writer.MetaData.MasterReferences!, {i}{(objData.GameReleaseOptions == null ? null : ", gameConstants")}, outputStreams));"); } i++; } fg.AppendLine("Parallel.Invoke(toDo.ToArray());"); using (var args = new ArgsWrapper(fg, $"{nameof(UtilityTranslation)}.{nameof(UtilityTranslation.CompileStreamsInto)}")) { args.Add("outputStreams.NotNull()"); args.Add("stream"); } } fg.AppendLine(); if (groupInstance != null) { using (var args = new FunctionWrapper(fg, $"public static void WriteGroupParallel<T>")) { args.Add("IGroupGetter<T> group"); args.Add($"{nameof(MasterReferenceReader)} masters"); args.Add("int targetIndex"); if (objData.GameReleaseOptions != null) { args.Add($"{nameof(GameConstants)} gameConstants"); } args.Add("Stream[] streamDepositArray"); if (objData.UsesStringFiles) { args.Add($"{nameof(StringsWriter)}? stringsWriter"); } args.Wheres.AddRange(groupInstance.TargetObjectGeneration.GenerateWhereClauses(LoquiInterfaceType.IGetter, groupInstance.TargetObjectGeneration.Generics)); } using (new BraceWrapper(fg)) { string gameConstantsStr; if (objData.GameReleaseOptions == null) { gameConstantsStr = $"{nameof(GameConstants)}.{obj.GetObjectData().GameCategory}"; } else { gameConstantsStr = "gameConstants"; } fg.AppendLine("if (group.RecordCache.Count == 0) return;"); fg.AppendLine($"var cuts = group.Cut(CutCount).ToArray();"); fg.AppendLine($"Stream[] subStreams = new Stream[cuts.Length + 1];"); fg.AppendLine($"byte[] groupBytes = new byte[{gameConstantsStr}.GroupConstants.HeaderLength];"); fg.AppendLine($"BinaryPrimitives.WriteInt32LittleEndian(groupBytes.AsSpan(), RecordTypes.GRUP.TypeInt);"); fg.AppendLine($"var groupByteStream = new MemoryStream(groupBytes);"); fg.AppendLine($"using (var stream = new MutagenWriter(groupByteStream, {gameConstantsStr}, dispose: false))"); using (new BraceWrapper(fg)) { fg.AppendLine($"stream.Position += 8;"); fg.AppendLine($"GroupBinaryWriteTranslation.WriteEmbedded<T>(group, stream);"); } fg.AppendLine($"subStreams[0] = groupByteStream;"); fg.AppendLine($"Parallel.ForEach(cuts, (cutItems, state, counter) =>"); using (new BraceWrapper(fg) { AppendSemicolon = true, AppendParenthesis = true }) { fg.AppendLine($"{nameof(MemoryTributary)} trib = new {nameof(MemoryTributary)}();"); fg.AppendLine($"var bundle = new {nameof(WritingBundle)}({gameConstantsStr})"); using (var prop = new PropertyCtorWrapper(fg)) { prop.Add($"{nameof(WritingBundle.MasterReferences)} = masters"); if (objData.UsesStringFiles) { prop.Add($"{nameof(WritingBundle.StringsWriter)} = stringsWriter"); } } fg.AppendLine($"using (var stream = new MutagenWriter(trib, bundle, dispose: false))"); using (new BraceWrapper(fg)) { fg.AppendLine($"foreach (var item in cutItems)"); using (new BraceWrapper(fg)) { fg.AppendLine($"item.WriteToBinary(stream);"); } } fg.AppendLine($"subStreams[(int)counter + 1] = trib;"); } fg.AppendLine($"UtilityTranslation.CompileSetGroupLength(subStreams, groupBytes);"); fg.AppendLine($"streamDepositArray[targetIndex] = new CompositeReadStream(subStreams, resetPositions: true);"); } fg.AppendLine(); } }
public override async Task GenerateInCommonMixin(ObjectGeneration obj, FileGeneration fg) { if (obj.GetObjectType() != ObjectType.Mod) { return; } var needsCatch = obj.GetObjectType() == ObjectType.Mod; string catchLine = needsCatch ? ".Catch(e => throw RecordException.Factory(e, obj.ModKey))" : string.Empty; string enderSemi = needsCatch ? string.Empty : ";"; fg.AppendLine("[DebuggerStepThrough]"); using (var args = new FunctionWrapper(fg, $"public static IEnumerable<IModContext<{obj.GetObjectData().GameCategory.Value.ModInterface(getter: false)}, TSetter, TGetter>> EnumerateMajorRecordContexts{obj.GetGenericTypes(MaskType.Normal, new string[] { "TSetter", "TGetter" })}")) { args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.IGetter, obj.Generics)); args.Wheres.Add($"where TSetter : class, IMajorRecordCommon, TGetter"); args.Wheres.Add($"where TGetter : class, IMajorRecordCommonGetter"); args.Add($"this {obj.Interface(getter: true, internalInterface: true)} obj"); args.Add($"{nameof(ILinkCache)} linkCache"); args.Add($"bool throwIfUnknown = true"); } using (new BraceWrapper(fg)) { using (var args = new FunctionWrapper(fg, $"return {obj.CommonClassInstance("obj", LoquiInterfaceType.IGetter, CommonGenerics.Class)}.EnumerateMajorRecordContexts")) { args.AddPassArg("obj"); args.AddPassArg("linkCache"); args.Add("type: typeof(TGetter)"); args.AddPassArg("throwIfUnknown"); } using (new DepthWrapper(fg)) { fg.AppendLine($".Select(m => m.AsType<{obj.GetObjectData().GameCategory.Value.ModInterface(getter: false)}, {nameof(IMajorRecordCommon)}, {nameof(IMajorRecordCommonGetter)}, TSetter, TGetter>()){enderSemi}"); if (needsCatch) { fg.AppendLine($"{catchLine};"); } } } fg.AppendLine(); fg.AppendLine("[DebuggerStepThrough]"); using (var args = new FunctionWrapper(fg, $"public static IEnumerable<IModContext<{obj.GetObjectData().GameCategory.Value.ModInterface(getter: false)}, IMajorRecordCommon, IMajorRecordCommonGetter>> EnumerateMajorRecordContexts{obj.GetGenericTypes(MaskType.Normal)}")) { args.Add($"this {obj.Interface(getter: true, internalInterface: true)} obj"); args.Add($"{nameof(ILinkCache)} linkCache"); args.Add($"Type type"); args.Add($"bool throwIfUnknown = true"); args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.IGetter, obj.Generics)); } using (new BraceWrapper(fg)) { using (var args = new ArgsWrapper(fg, $"return {obj.CommonClassInstance("obj", LoquiInterfaceType.IGetter, CommonGenerics.Class)}.EnumerateMajorRecordContexts")) { args.AddPassArg("obj"); args.AddPassArg("linkCache"); args.AddPassArg("type"); args.AddPassArg("throwIfUnknown"); } } fg.AppendLine(); }