public override async Task LoadWrapup(ObjectGeneration obj) { try { await Task.WhenAll( obj.IterateFields(expandSets : SetMarkerType.ExpandSets.TrueAndInclude, nonIntegrated : true) .Select(async(field) => { await SetContainerSubTriggers(obj, field); })); foreach (var field in obj.IterateFields(expandSets: SetMarkerType.ExpandSets.TrueAndInclude, nonIntegrated: true)) { await SetRecordTrigger(obj, field, field.GetFieldData()); } await SetObjectTrigger(obj); obj.GetObjectData().WiringComplete.Complete(); await base.LoadWrapup(obj); } catch (Exception ex) { obj.GetObjectData().WiringComplete.SetException(ex); throw; } }
public override async Task PostLoad(ObjectGeneration obj) { try { foreach (var field in obj.IterateFields(expandSets: SetMarkerType.ExpandSets.TrueAndInclude, nonIntegrated: true)) { MutagenFieldData subData; switch (field) { case WrapperType wrapper: subData = wrapper.SubTypeGeneration.GetFieldData(); break; case DictType_KeyedValue dict: subData = dict.ValueTypeGen.GetFieldData(); break; default: continue; } subData.Parent = field; } } catch (Exception ex) { obj.GetObjectData().WiringComplete.SetException(ex); throw; } }
public override Task GenerateInRegistration(ObjectGeneration obj, FileGeneration fg) { var objData = obj.GetObjectData(); GenerateConverterMember(fg, obj.BaseClass, objData.BaseRecordTypeConverter, "Base"); foreach (var field in obj.IterateFields(expandSets: SetMarkerType.ExpandSets.FalseAndInclude, nonIntegrated: true)) { LoquiType loquiType = field as LoquiType; if (loquiType == null) { switch (field) { case WrapperType wrapper: loquiType = wrapper.SubTypeGeneration as LoquiType; if (loquiType != null) { break; } continue; default: continue; } } var fieldData = loquiType.GetFieldData(); GenerateConverterMember(fg, loquiType.TargetObjectGeneration, fieldData.RecordTypeConverter, field.Name); } return(base.GenerateInRegistration(obj, fg)); }
public async IAsyncEnumerable <PassedLengths> IteratePassedLengths( ObjectGeneration obj, bool forOverlay, string passedLenPrefix = null, bool includeBaseClass = false, SetMarkerType.ExpandSets expand = SetMarkerType.ExpandSets.FalseAndInclude) { await foreach (var item in IteratePassedLengths( obj, obj.IterateFields( expandSets: expand, nonIntegrated: true, includeBaseClass: true), forOverlay: forOverlay, passedLenPrefix: passedLenPrefix)) { if (includeBaseClass || obj.Fields.Contains(item.Field) || ((expand == SetMarkerType.ExpandSets.True || expand == SetMarkerType.ExpandSets.TrueAndInclude) && obj.Fields.WhereCastable <TypeGeneration, DataType>().Any(d => d.SubFields.Contains(item.Field)))) { yield return(item); } } }
private void GenerateGetGroup(ObjectGeneration obj, FileGeneration fg) { using (var args = new FunctionWrapper(fg, "public object GetGroup<TMajor>")) { args.Wheres.Add($"where TMajor : {nameof(IMajorRecordCommonGetter)}"); args.Add($"{obj.Interface(getter: true)} obj"); } using (new BraceWrapper(fg)) { fg.AppendLine("switch (typeof(TMajor).Name)"); using (new BraceWrapper(fg)) { foreach (var field in obj.IterateFields()) { if (!(field is LoquiType loqui)) { continue; } if (loqui.TargetObjectGeneration?.GetObjectData().ObjectType != ObjectType.Group) { continue; } if (!loqui.TryGetSpecificationAsObject("T", out var subObj)) { throw new ArgumentException(); } fg.AppendLine($"case \"{subObj.Name}\":"); fg.AppendLine($"case \"{subObj.Interface(getter: true)}\":"); fg.AppendLine($"case \"{subObj.Interface(getter: false)}\":"); if (subObj.HasInternalGetInterface) { fg.AppendLine($"case \"{subObj.Interface(getter: true, internalInterface: true)}\":"); } if (subObj.HasInternalSetInterface) { fg.AppendLine($"case \"{subObj.Interface(getter: false, internalInterface: true)}\":"); } using (new DepthWrapper(fg)) { if (loqui.TargetObjectGeneration.Name == "ListGroup") { fg.AppendLine($"return obj.{field.Name}.Records;"); } else { fg.AppendLine($"return obj.{field.Name}.RecordCache;"); } } } fg.AppendLine("default:"); using (new DepthWrapper(fg)) { fg.AppendLine("throw new ArgumentException($\"Unknown major record type: {typeof(TMajor)}\");"); } } } fg.AppendLine(); }
protected IEnumerable <TypeGeneration> GetEmbeddedFields(ObjectGeneration obj) { foreach (var field in obj.IterateFields(expandSets: SetMarkerType.ExpandSets.FalseAndInclude)) { if (!field.GetFieldData().HasTrigger) { yield return(field); } } }
public static bool StructNullable(this ObjectGeneration objGen) { return(objGen.IterateFields().Any((f) => { if (!f.Nullable) { return false; } var data = f.GetFieldData(); return !data.HasTrigger; })); }
public static async Task <Case> HasMajorRecords(ObjectGeneration obj, bool includeBaseClass, bool includeSelf, GenericSpecification specifications = null) { if (obj.Name == "ListGroup") { return(Case.Yes); } foreach (var field in obj.IterateFields(includeBaseClass: includeBaseClass)) { if (field is LoquiType loqui) { if (includeSelf && loqui.TargetObjectGeneration != null && await loqui.TargetObjectGeneration.IsMajorRecord()) { return(Case.Yes); } if (await HasMajorRecords(loqui, includeBaseClass, specifications) == Case.Yes) { return(Case.Yes); } } else if (field is ContainerType cont) { if (cont.SubTypeGeneration is LoquiType contLoqui) { if (await HasMajorRecords(contLoqui, includeBaseClass, specifications) == Case.Yes) { return(Case.Yes); } } } else if (field is DictType dict) { if (dict.ValueTypeGen is LoquiType valLoqui) { if (await HasMajorRecords(valLoqui, includeBaseClass, specifications) == Case.Yes) { return(Case.Yes); } } if (dict.KeyTypeGen is LoquiType keyLoqui) { if (await HasMajorRecords(keyLoqui, includeBaseClass, specifications) == Case.Yes) { return(Case.Yes); } } } } return(Case.No); }
protected override async Task PreCreateLoop(ObjectGeneration obj, FileGeneration fg) { foreach (var field in obj.IterateFields(nonIntegrated: true, expandSets: SetMarkerType.ExpandSets.FalseAndInclude)) { if (!(field is DataType set)) { continue; } for (int i = 0; i < set.BreakIndices.Count; i++) { fg.AppendLine($"item.{set.StateName} |= {obj.Name}.{set.EnumName}.Break{i};"); } } }
private void GenerateCustomCreatePartials(ObjectGeneration obj, FileGeneration fg) { foreach (var field in obj.IterateFields(nonIntegrated: true)) { if (field.GetFieldData().Binary != BinaryGenerationType.Custom && !(field is CustomLogic)) { continue; } CustomLogicTranslationGeneration.GenerateCreatePartialMethods( fg: fg, obj: obj, field: field, isAsync: false); } }
public override async Task GenerateInClass(ObjectGeneration obj, FileGeneration fg) { await base.GenerateInClass(obj, fg); List <string> enumTypes; int breaks; foreach (var field in obj.IterateFields(expandSets: SetMarkerType.ExpandSets.FalseAndInclude)) { if (!(field is DataType dataType)) { continue; } enumTypes = new List <string>(); breaks = 0; int ranges = 0; foreach (var node in dataType.Node.Element(XName.Get(Loqui.Generation.Constants.FIELDS, LoquiGenerator.Namespace)).Elements()) { switch (node.Name.LocalName) { case DataType.BREAK: enumTypes.Add("Break" + breaks++); break; case DataType.RANGE: enumTypes.Add("Range" + ranges++); break; default: break; } } fg.AppendLine("[Flags]"); fg.AppendLine($"public enum {dataType.EnumName}"); using (new BraceWrapper(fg)) { using (var comma = new CommaWrapper(fg)) { var term = 1; for (int i = 0; i < enumTypes.Count; i++) { comma.Add($"{enumTypes[i]} = {term}"); term *= 2; } } } } }
public static async IAsyncEnumerable <ObjectGeneration> IterateMajorRecords(ObjectGeneration obj, bool includeBaseClass, bool includeSelf, GenericSpecification specifications = null) { foreach (var field in obj.IterateFields(includeBaseClass: includeBaseClass)) { if (field is LoquiType loqui) { if (includeSelf && loqui.TargetObjectGeneration != null && await loqui.TargetObjectGeneration.IsMajorRecord()) { yield return(loqui.TargetObjectGeneration); } await foreach (var item in IterateMajorRecords(loqui, includeBaseClass, specifications)) { yield return(item); } } else if (field is ContainerType cont) { if (cont.SubTypeGeneration is LoquiType contLoqui) { await foreach (var item in IterateMajorRecords(contLoqui, includeBaseClass, specifications)) { yield return(item); } } } else if (field is DictType dict) { if (dict.ValueTypeGen is LoquiType valLoqui) { await foreach (var item in IterateMajorRecords(valLoqui, includeBaseClass, specifications)) { yield return(item); } } if (dict.KeyTypeGen is LoquiType keyLoqui) { await foreach (var item in IterateMajorRecords(keyLoqui, includeBaseClass, specifications)) { yield return(item); } } } } }
public override async Task LoadWrapup(ObjectGeneration obj) { await base.LoadWrapup(obj); foreach (var field in obj.IterateFields(expandSets: SetMarkerType.ExpandSets.FalseAndInclude)) { if (!(field is DataType dataType)) { continue; } XElement elem = new XElement("Enum"); elem.Add(new XAttribute(Loqui.Generation.Constants.NAME, dataType.StateName)); elem.Add(new XAttribute(Loqui.Generation.Constants.ENUM_NAME, $"{obj.ObjectName}.{dataType.EnumName}")); elem.Add(new XAttribute("binary", nameof(BinaryGenerationType.NoGeneration))); elem.Add(new XAttribute(Loqui.Generation.Constants.HAS_BEEN_SET, "false")); await obj.LoadField(elem, requireName : true, add : true); } }
public static async Task <bool> GetNeedsMasters(this ObjectGeneration objGen) { if (objGen.GetObjectType() == ObjectType.Group) { return(true); } foreach (var field in objGen.IterateFields()) { if (field is FormKeyType) { return(true); } if (field is FormIDType) { return(true); } if (field is ContainerType cont) { if (cont.SubTypeGeneration is LoquiType loqui && (loqui.TargetObjectGeneration == null || await loqui.TargetObjectGeneration.GetNeedsMasters())) { return(true); } } if (field is DictType dict) { if (dict.ValueTypeGen is LoquiType loqui && (loqui.TargetObjectGeneration == null || await loqui.TargetObjectGeneration.GetNeedsMasters())) { return(true); } } } foreach (var baseObj in objGen.BaseClassTrail()) { if (await baseObj.GetNeedsMasters()) { return(true); } } return(false); }
public static async Task <Dictionary <ObjectGeneration, HashSet <TypeGeneration> > > FindDeepRecords(ObjectGeneration obj) { var deepRecordMapping = new Dictionary <ObjectGeneration, HashSet <TypeGeneration> >(); foreach (var field in obj.IterateFields()) { if (field is LoquiType loqui) { var groupType = field as GroupType; await foreach (var deepObj in MajorRecordModule.IterateMajorRecords(loqui, includeBaseClass: true)) { if (groupType != null && groupType.GetGroupTarget() == deepObj) { continue; } if (loqui.TargetObjectGeneration == deepObj) { continue; } deepRecordMapping.GetOrAdd(deepObj).Add(field); } } else if (field is ContainerType cont) { if (!(cont.SubTypeGeneration is LoquiType subLoqui)) { continue; } await foreach (var deepObj in MajorRecordModule.IterateMajorRecords(subLoqui, includeBaseClass: true)) { if (subLoqui.TargetObjectGeneration == deepObj) { continue; } deepRecordMapping.GetOrAdd(deepObj).Add(field); } } } return(deepRecordMapping); }
public static async Task <LoquiType> GetGroupLoquiType(this ObjectGeneration objGen) { await objGen.LoadingCompleteTask.Task; if (objGen.GetObjectType() != ObjectType.Group) { throw new ArgumentException(); } foreach (var field in objGen.IterateFields()) { if (field is ContainerType cont) { return(cont.SubTypeGeneration as LoquiType); } else if (field is DictType dictType) { return(dictType.ValueTypeGen as LoquiType); } } throw new ArgumentException(); }
public override async Task LoadWrapup(ObjectGeneration obj) { var objData = obj.GetObjectData(); await Task.WhenAll( objData.WiringComplete.Task, objData.DataTypeModuleComplete.Task); bool triggerEncountered = false; foreach (var field in obj.IterateFields( nonIntegrated: true, expandSets: SetMarkerType.ExpandSets.False)) { if (field is SetMarkerType) { continue; } if (field.Derivative || !field.IntegrateField) { continue; } var data = field.GetFieldData(); if (data.Binary == BinaryGenerationType.NoGeneration) { continue; } if (data.HasTrigger) { triggerEncountered = true; } else if (triggerEncountered) { throw new ArgumentException($"{obj.Name} cannot have an embedded field without a record type after ones with record types have been defined: {field.Name}"); } } await base.LoadWrapup(obj); }
public override List <AspectInterfaceData> Interfaces(ObjectGeneration obj) { var nameField = obj.IterateFields(includeBaseClass: true).OfType <StringType>().Single(x => x.Name == "Name"); var list = new List <AspectInterfaceData>(); AddInterfaces(list, nameof(INamedRequired), nameof(INamedRequiredGetter)); if (nameField.Nullable) { AddInterfaces(list, nameof(INamed), nameof(INamedGetter)); } if (nameField.Translated.HasValue) { AddInterfaces(list, nameof(ITranslatedNamedRequired), nameof(ITranslatedNamedRequiredGetter)); if (nameField.Nullable) { AddInterfaces(list, nameof(ITranslatedNamed), nameof(ITranslatedNamedGetter)); } } return(list); }
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 static async Task <Case> HasLinks(ObjectGeneration obj, bool includeBaseClass, GenericSpecification specifications = null) { if (obj.Name == "MajorRecord") { return(Case.Yes); } if (obj.IterateFields(includeBaseClass: includeBaseClass).Any((f) => f is FormLinkType)) { return(Case.Yes); } Case bestCase = Case.No; foreach (var field in obj.IterateFields(includeBaseClass: includeBaseClass)) { if (field is LoquiType loqui) { var subCase = await HasLinks(loqui, includeBaseClass, specifications); if (subCase > bestCase) { bestCase = subCase; } } else if (field is ContainerType cont) { if (cont.SubTypeGeneration is LoquiType contLoqui) { var subCase = await HasLinks(contLoqui, includeBaseClass, specifications); if (subCase > bestCase) { bestCase = subCase; } } else if (cont.SubTypeGeneration is FormLinkType) { return(Case.Yes); } } else if (field is DictType dict) { if (dict.ValueTypeGen is LoquiType valLoqui) { var subCase = await HasLinks(valLoqui, includeBaseClass, specifications); if (subCase > bestCase) { bestCase = subCase; } } if (dict.KeyTypeGen is LoquiType keyLoqui) { var subCase = await HasLinks(keyLoqui, includeBaseClass, specifications); if (subCase > bestCase) { bestCase = subCase; } } if (dict.ValueTypeGen is FormLinkType) { return(Case.Yes); } } } // If no, check subclasses if (bestCase == Case.No) { foreach (var inheritingObject in await obj.InheritingObjects()) { var subCase = await HasLinks(inheritingObject, includeBaseClass : false, specifications : specifications); if (subCase != Case.No) { return(Case.Maybe); } } } return(bestCase); }
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})"); }
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 void Generate(ObjectGeneration obj, FileGeneration fg) { fg.AppendLine($"public class {obj.Name}_Mask<T> {(obj.HasBaseObject ? " : " + obj.BaseClass.GetMaskString("T") : string.Empty)}"); using (new BraceWrapper(fg)) { foreach (var field in obj.Fields) { if (!FieldMapping.TryGetValue(field.GetType(), out MaskModuleField fieldGen)) { fieldGen = TypicalField; } fieldGen.GenerateForField(fg, field, "T"); } } fg.AppendLine(); fg.AppendLine($"public class {obj.Name}_ErrorMask : {(obj.HasBaseObject ? $"{obj.BaseClass.Name}_ErrorMask" : "IErrorMask")}"); using (new BraceWrapper(fg)) { fg.AppendLine("public Exception Overall { get; set; }"); fg.AppendLine("private List<string> _warnings;"); fg.AppendLine("public List<string> Warnings"); using (new BraceWrapper(fg)) { fg.AppendLine("get"); using (new BraceWrapper(fg)) { fg.AppendLine("if (_warnings == null)"); using (new BraceWrapper(fg)) { fg.AppendLine("_warnings = new List<string>();"); } fg.AppendLine("return _warnings;"); } } foreach (var field in obj.Fields) { if (!FieldMapping.TryGetValue(field.GetType(), out MaskModuleField fieldGen)) { fieldGen = TypicalField; } fieldGen.GenerateForErrorMask(fg, field); } fg.AppendLine(); fg.AppendLine("public void SetNthException(ushort index, Exception ex)"); using (new BraceWrapper(fg)) { fg.AppendLine("switch (index)"); using (new BraceWrapper(fg)) { foreach (var item in obj.IterateFields()) { fg.AppendLine($"case {item.Index}:"); using (new DepthWrapper(fg)) { if (!FieldMapping.TryGetValue(item.Field.GetType(), out MaskModuleField fieldGen)) { fieldGen = TypicalField; } fieldGen.GenerateSetException(fg, item.Field); fg.AppendLine("break;"); } } obj.GenerateStandardIndexDefault(fg, "SetNthException", "index", false); } } fg.AppendLine(); fg.AppendLine("public void SetNthMask(ushort index, object obj)"); using (new BraceWrapper(fg)) { fg.AppendLine("switch (index)"); using (new BraceWrapper(fg)) { foreach (var item in obj.IterateFields()) { fg.AppendLine($"case {item.Index}:"); using (new DepthWrapper(fg)) { if (!FieldMapping.TryGetValue(item.Field.GetType(), out MaskModuleField fieldGen)) { fieldGen = TypicalField; } fieldGen.GenerateSetMask(fg, item.Field); fg.AppendLine("break;"); } } obj.GenerateStandardIndexDefault(fg, "SetNthMask", "index", false); } } } }
public override async Task GenerateInClass(ObjectGeneration obj, FileGeneration fg) { if (obj.GetObjectData().ObjectType != ObjectType.Mod) { return; } var objData = obj.GetObjectData(); // Game release member if (objData.GameReleaseOptions != null) { fg.AppendLine($"public {ReleaseEnumName(obj)} {ReleaseEnumName(obj)} {{ get; }}"); fg.AppendLine($"public override {nameof(GameRelease)} GameRelease => {ReleaseEnumName(obj)}.ToGameRelease();"); } else { fg.AppendLine($"public override {nameof(GameRelease)} GameRelease => {nameof(GameRelease)}.{obj.GetObjectData().GameCategory};"); } // Interfaces fg.AppendLine($"IReadOnlyCache<T, {nameof(FormKey)}> {nameof(IModGetter)}.{nameof(IModGetter.GetTopLevelGroupGetter)}<T>() => this.{nameof(IModGetter.GetTopLevelGroupGetter)}<T>();"); fg.AppendLine($"ICache<T, {nameof(FormKey)}> {nameof(IMod)}.{nameof(IMod.GetGroup)}<T>() => this.GetGroup<T>();"); fg.AppendLine($"void IModGetter.WriteToBinary(string path, {nameof(BinaryWriteParameters)}? param) => this.WriteToBinary(path, importMask: null, param: param);"); fg.AppendLine($"void IModGetter.WriteToBinaryParallel(string path, {nameof(BinaryWriteParameters)}? param) => this.WriteToBinaryParallel(path, param);"); fg.AppendLine($"IMask<bool> {nameof(IEqualsMask)}.{nameof(IEqualsMask.GetEqualsMask)}(object rhs, EqualsMaskHelper.Include include = EqualsMaskHelper.Include.OnlyFailures) => {obj.MixInClassName}.GetEqualsMask(this, ({obj.Interface(getter: true, internalInterface: true)})rhs, include);"); // Localization enabled member if (obj.GetObjectData().UsesStringFiles) { fg.AppendLine($"public override bool CanUseLocalization => true;"); fg.AppendLine($"public override bool UsingLocalization"); using (new BraceWrapper(fg)) { fg.AppendLine($"get => this.ModHeader.Flags.HasFlag({obj.GetObjectData().GameCategory}ModHeader.HeaderFlag.Localized);"); fg.AppendLine($"set => this.ModHeader.Flags.SetFlag({obj.GetObjectData().GameCategory}ModHeader.HeaderFlag.Localized, value);"); } } else { fg.AppendLine($"public override bool CanUseLocalization => false;"); fg.AppendLine($"public override bool UsingLocalization"); using (new BraceWrapper(fg)) { fg.AppendLine("get => false;"); fg.AppendLine("set => throw new ArgumentException(\"Tried to set localization flag on unsupported mod type\");"); } } // Master references member fg.AppendLine($"[DebuggerBrowsable(DebuggerBrowsableState.Never)]"); fg.AppendLine($"IList<MasterReference> IMod.MasterReferences => this.ModHeader.MasterReferences;"); fg.AppendLine($"[DebuggerBrowsable(DebuggerBrowsableState.Never)]"); fg.AppendLine($"IReadOnlyList<IMasterReferenceGetter> IModGetter.MasterReferences => this.ModHeader.MasterReferences;"); // NextObjectID member fg.AppendLine($"[DebuggerBrowsable(DebuggerBrowsableState.Never)]"); fg.AppendLine($"uint IMod.NextFormID"); using (new BraceWrapper(fg)) { fg.AppendLine($"get => this.ModHeader.Stats.NextFormID;"); fg.AppendLine($"set => this.ModHeader.Stats.NextFormID = value;"); } fg.AppendLine($"[DebuggerBrowsable(DebuggerBrowsableState.Never)]"); fg.AppendLine($"uint IModGetter.NextFormID => this.ModHeader.Stats.NextFormID;"); using (var args = new FunctionWrapper(fg, $"public {obj.Name}")) { args.Add($"{nameof(ModKey)} modKey"); if (objData.GameReleaseOptions != null) { args.Add($"{ReleaseEnumName(obj)} release"); } } using (new DepthWrapper(fg)) { fg.AppendLine(": base(modKey)"); } using (new BraceWrapper(fg)) { fg.AppendLine("this.ModHeader.Stats.NextFormID = GetDefaultInitialNextFormID();"); if (objData.GameReleaseOptions != null) { fg.AppendLine($"this.{ReleaseEnumName(obj)} = release;"); } await obj.GenerateInitializer(fg); fg.AppendLine($"CustomCtor();"); } using (var args = new FunctionWrapper(fg, "public void AddRecords")) { args.Add($"{obj.Name} rhsMod"); args.Add($"GroupMask? mask = null"); } using (new BraceWrapper(fg)) { foreach (var field in obj.IterateFields()) { if (!(field is LoquiType loqui)) { continue; } if (loqui.TargetObjectGeneration.GetObjectType() != ObjectType.Group) { continue; } fg.AppendLine($"if (mask?.{field.Name} ?? true)"); using (new BraceWrapper(fg)) { if (loqui.TargetObjectGeneration.Name == "Group") { fg.AppendLine($"this.{field.Name}.RecordCache.Set(rhsMod.{field.Name}.RecordCache.Items);"); } else { fg.AppendLine($"if (rhsMod.{field.Name}.Records.Count > 0)"); using (new BraceWrapper(fg)) { fg.AppendLine("throw new NotImplementedException(\"Cell additions need implementing\");"); } } } } } fg.AppendLine(); using (var args = new FunctionWrapper(fg, $"public Dictionary<FormKey, {nameof(IMajorRecordCommon)}> CopyInDuplicate")) { args.Add($"{obj.Name} rhs"); args.Add($"GroupMask? mask = null"); } using (new BraceWrapper(fg)) { fg.AppendLine($"var duppedRecords = new List<({nameof(IMajorRecordCommon)} Record, FormKey OriginalFormKey)>();"); foreach (var field in obj.IterateFields()) { if (!(field is LoquiType loqui)) { continue; } if (loqui.TargetObjectGeneration.GetObjectType() != ObjectType.Group) { continue; } var dictGroup = loqui.TargetObjectGeneration.Name == "Group"; fg.AppendLine($"if (mask?.{field.Name} ?? true)"); using (new BraceWrapper(fg)) { fg.AppendLine($"this.{field.Name}.{(dictGroup ? "RecordCache" : "Records")}.{(dictGroup ? "Set" : "AddRange")}("); using (new DepthWrapper(fg)) { fg.AppendLine($"rhs.{field.Name}.Records"); using (new DepthWrapper(fg)) { fg.AppendLine($".Select(i => i.Duplicate(this.GetNextFormKey, duppedRecords))"); fg.AppendLine($".Cast<{loqui.GetGroupTarget().Name}>());"); } } } } fg.AppendLine($"var router = new Dictionary<FormKey, {nameof(IMajorRecordCommon)}>();"); fg.AppendLine($"router.Set(duppedRecords.Select(dup => new KeyValuePair<FormKey, {nameof(IMajorRecordCommon)}>(dup.OriginalFormKey, dup.Record)));"); fg.AppendLine($"var mapping = new Dictionary<FormKey, FormKey>();"); fg.AppendLine($"var package = this.{nameof(ILinkCacheExt.ToImmutableLinkCache)}();"); fg.AppendLine("foreach (var rec in router.Values)"); using (new BraceWrapper(fg)) { fg.AppendLine($"rec.RemapLinks(mapping);"); } fg.AppendLine($"return router;"); } fg.AppendLine(); using (var args = new FunctionWrapper(fg, "public override void SyncRecordCount")) { } using (new BraceWrapper(fg)) { fg.AppendLine("this.ModHeader.Stats.NumRecords = GetRecordCount();"); } fg.AppendLine(); using (var args = new FunctionWrapper(fg, "public uint GetRecordCount")) { } using (new BraceWrapper(fg)) { fg.AppendLine("uint count = (uint)this.EnumerateMajorRecords().Count();"); foreach (var field in obj.IterateFields()) { if (!(field is LoquiType loqui)) { continue; } if (loqui.TargetObjectGeneration.GetObjectType() != ObjectType.Group) { continue; } if (loqui.TargetObjectGeneration.Name == "ListGroup") { fg.AppendLine($"count += {field.Name}.Records.Count > 0 ? 1 : default(uint);"); } else { fg.AppendLine($"count += {field.Name}.RecordCache.Count > 0 ? 1 : default(uint);"); } } fg.AppendLine("GetCustomRecordCount((customCount) => count += customCount);"); fg.AppendLine("return count;"); } fg.AppendLine(); fg.AppendLine("partial void GetCustomRecordCount(Action<uint> setter);"); fg.AppendLine(); await base.GenerateInClass(obj, fg); }
public override async Task GenerateInVoid(ObjectGeneration obj, FileGeneration fg) { if (obj.GetObjectType() != ObjectType.Mod) { return; } using (new NamespaceWrapper(fg, obj.Namespace)) { var objData = obj.GetObjectData(); fg.AppendLine("public class GroupMask"); using (new BraceWrapper(fg)) { foreach (var field in obj.IterateFields()) { if (!(field is LoquiType loqui)) { continue; } if (loqui.TargetObjectGeneration == null) { continue; } if (loqui.TargetObjectGeneration.GetObjectType() != ObjectType.Group) { continue; } fg.AppendLine($"public bool {loqui.Name};"); } fg.AppendLine("public GroupMask()"); using (new BraceWrapper(fg)) { } fg.AppendLine("public GroupMask(bool defaultValue)"); using (new BraceWrapper(fg)) { foreach (var field in obj.IterateFields()) { if (!(field is LoquiType loqui)) { continue; } if (loqui.TargetObjectGeneration == null) { continue; } if (loqui.TargetObjectGeneration.GetObjectType() != ObjectType.Group) { continue; } fg.AppendLine($"{loqui.Name} = defaultValue;"); } } } fg.AppendLine(); fg.AppendLine($"public interface I{obj.Name}DisposableGetter : {obj.Interface(getter: true, internalInterface: true)}, IModDisposeGetter"); using (new BraceWrapper(fg)) { } fg.AppendLine(); if (objData.GameReleaseOptions != null) { using (var comment = new CommentWrapper(fg)) { comment.Summary.AppendLine($"Different game release versions a {ModName(obj)} mod can have"); } fg.AppendLine($"public enum {ReleaseEnumName(obj)}"); using (new BraceWrapper(fg)) { using (var comma = new CommaWrapper(fg)) { foreach (var opt in objData.GameReleaseOptions) { comma.Add($"{opt} = {(int)opt}"); } } } fg.AppendLine(); using (var c = new ClassWrapper(fg, $"{ReleaseEnumName(obj)}Ext")) { c.Static = true; } using (new BraceWrapper(fg)) { using (var args = new FunctionWrapper(fg, $"public static {nameof(GameRelease)} ToGameRelease")) { args.Add($"this {ReleaseEnumName(obj)} release"); } using (new BraceWrapper(fg)) { fg.AppendLine("return release switch"); using (new BraceWrapper(fg) { AppendSemicolon = true }) { using (var comma = new CommaWrapper(fg)) { foreach (var item in objData.GameReleaseOptions) { comma.Add($"{ReleaseEnumName(obj)}.{item} => {nameof(GameRelease)}.{item}"); } comma.Add("_ => throw new ArgumentException()"); } } } fg.AppendLine(); using (var args = new FunctionWrapper(fg, $"public static {ReleaseEnumName(obj)} To{ReleaseEnumName(obj)}")) { args.Add($"this {nameof(GameRelease)} release"); } using (new BraceWrapper(fg)) { fg.AppendLine("return release switch"); using (new BraceWrapper(fg) { AppendSemicolon = true }) { using (var comma = new CommaWrapper(fg)) { foreach (var item in objData.GameReleaseOptions) { comma.Add($"{nameof(GameRelease)}.{item} => {ReleaseEnumName(obj)}.{item}"); } comma.Add("_ => throw new ArgumentException()"); } } } } } } }
private async Task GenerateForMod(ObjectGeneration obj, FileGeneration fg) { using (var args = new FunctionWrapper(fg, $"public static Task<{obj.Name}> CreateFromXmlFolder")) { args.Add("DirectoryPath dir"); args.Add("ModKey modKey"); } using (new BraceWrapper(fg)) { using (var args = new ArgsWrapper(fg, "return CreateFromXmlFolder")) { args.Add("dir: dir"); args.Add("modKey: modKey"); args.Add("errorMask: null"); } } fg.AppendLine(); using (var args = new FunctionWrapper(fg, $"public static async Task<({obj.Name} Mod, {obj.Mask(MaskType.Error)} ErrorMask)> CreateFromXmlFolderWithErrorMask")) { args.Add("DirectoryPath dir"); args.Add("ModKey modKey"); } using (new BraceWrapper(fg)) { fg.AppendLine("ErrorMaskBuilder? errorMaskBuilder = new ErrorMaskBuilder();"); using (var args = new ArgsWrapper(fg, "var ret = await CreateFromXmlFolder")) { args.Add("dir: dir"); args.Add("modKey: modKey"); args.Add("errorMask: errorMaskBuilder"); } fg.AppendLine($"var errorMask = {obj.Mask(MaskType.Error)}.Factory(errorMaskBuilder);"); fg.AppendLine("return (ret, errorMask);"); } fg.AppendLine(); using (var args = new FunctionWrapper(fg, $"public static async Task<{obj.Name}> CreateFromXmlFolder")) { args.Add("DirectoryPath dir"); args.Add("ModKey modKey"); args.Add("ErrorMaskBuilder? errorMask"); } using (new BraceWrapper(fg)) { fg.AppendLine($"var item = new {obj.Name}(modKey);"); fg.AppendLine($"var tasks = new List<Task>();"); foreach (var field in obj.IterateFields()) { if (field.GetFieldData().CustomFolder) { using (var args = new ArgsWrapper(fg, $"tasks.Add(Task.Run(() => item.CreateFromXmlFolder{field.Name}", suffixLine: "))")) { args.Add("dir: dir"); args.Add($"name: nameof({field.Name})"); args.Add($"index: (int){field.IndexEnumName}"); args.Add($"errorMask: errorMask"); } continue; } if (!(field is LoquiType loqui)) { throw new ArgumentException(); } switch (loqui.TargetObjectGeneration.GetObjectType()) { case ObjectType.Record: using (var args = new ArgsWrapper(fg, $"item.{field.Name}.CopyInFromXml")) { args.Add($"path: Path.Combine(dir.Path, \"{field.Name}.xml\")"); args.Add($"errorMask: errorMask"); args.Add($"translationMask: null"); } break; case ObjectType.Group: if (!loqui.TryGetSpecificationAsObject("T", out var subObj)) { continue; } using (var args = new ArgsWrapper(fg, $"tasks.Add(Task.Run(() => item.{field.Name}.CreateFromXmlFolder<{subObj.Name}>", suffixLine: "))")) { args.Add($"dir: dir"); args.Add($"name: nameof({field.Name})"); args.Add($"errorMask: errorMask"); args.Add($"index: (int){field.IndexEnumName}"); } break; default: break; } } fg.AppendLine("await Task.WhenAll(tasks);"); fg.AppendLine("return item;"); } fg.AppendLine(); using (var args = new FunctionWrapper(fg, $"public async Task<{obj.Mask(MaskType.Error)}?> WriteToXmlFolder")) { args.Add("DirectoryPath dir"); args.Add("bool doMasks = true"); } using (new BraceWrapper(fg)) { fg.AppendLine($"ErrorMaskBuilder? errorMaskBuilder = null;"); fg.AppendLine("dir.Create();"); fg.AppendLine("using (new FolderCleaner(dir, FolderCleaner.CleanType.AccessTime))"); using (new BraceWrapper(fg)) { fg.AppendLine($"var tasks = new List<Task>();"); foreach (var field in obj.IterateFields()) { if (!(field is LoquiType loqui)) { throw new ArgumentException(); } if (field.GetFieldData().CustomFolder) { using (var args = new ArgsWrapper(fg, $"tasks.Add(Task.Run(() => WriteToXmlFolder{field.Name}", suffixLine: "))")) { args.Add("dir: dir"); args.Add($"name: nameof({field.Name})");; args.Add($"index: (int){field.IndexEnumName}"); args.Add($"errorMask: errorMaskBuilder"); } continue; } switch (loqui.TargetObjectGeneration.GetObjectType()) { case ObjectType.Record: using (var args = new ArgsWrapper(fg, $"tasks.Add(Task.Run(() => this.{field.Name}.WriteToXml", suffixLine: "))")) { args.Add($"path: Path.Combine(dir.Path, \"{field.Name}.xml\")"); args.Add($"errorMask: errorMaskBuilder"); args.Add($"translationMask: null"); } break; case ObjectType.Group: ObjectGeneration subObj; if (field is GroupType group) { if (!group.TryGetSpecificationAsObject("T", out subObj)) { continue; } using (var args = new ArgsWrapper(fg, $"tasks.Add(Task.Run(() => {field.Name}.WriteToXmlFolder<{subObj.Name}, {subObj.Mask(MaskType.Error)}>", suffixLine: "))")) { args.Add($"dir: dir.Path"); args.Add($"name: nameof({field.Name})"); args.Add($"errorMask: errorMaskBuilder"); args.Add($"index: (int){field.IndexEnumName}"); } } else { using (var args = new ArgsWrapper(fg, $"tasks.Add(Task.Run(() => {field.Name}.WriteToXmlFolder", suffixLine: "))")) { args.Add($"dir: dir.Path"); args.Add($"name: nameof({field.Name})"); args.Add($"errorMask: errorMaskBuilder"); args.Add($"index: (int){field.IndexEnumName}"); } } break; default: break; } } fg.AppendLine("await Task.WhenAll(tasks);"); } fg.AppendLine("return null;"); } }
public async IAsyncEnumerable <RecordType> GetAllRecordTypes(ObjectGeneration obj) { HashSet <RecordType> recordTypes = new HashSet <RecordType>(); if (obj.TryGetRecordType(out var recType)) { recordTypes.Add(recType); } var data = obj.GetObjectData(); var trigRecTypes = await data.GenerationTypes; recordTypes.Add(trigRecTypes.SelectMany((kv) => kv.Key)); if (data.EndMarkerType.HasValue) { recordTypes.Add(data.EndMarkerType.Value); } foreach (var field in obj.IterateFields(expandSets: SetMarkerType.ExpandSets.FalseAndInclude, nonIntegrated: true)) { var fieldData = field.GetFieldData(); if (fieldData.RecordType.HasValue) { recordTypes.Add(fieldData.RecordType.Value); } recordTypes.Add(fieldData.TriggeringRecordTypes); if (fieldData.MarkerType.HasValue) { recordTypes.Add(fieldData.MarkerType.Value); } foreach (var subType in fieldData.SubLoquiTypes.Keys) { recordTypes.Add(subType); } if (field is ContainerType contType) { if (!contType.SubTypeGeneration.TryGetFieldData(out var subData)) { continue; } if (contType.CustomData.TryGetValue(ListBinaryTranslationGeneration.CounterRecordType, out var counterRecType) && !string.IsNullOrWhiteSpace((string)counterRecType)) { recordTypes.Add(new RecordType((string)counterRecType)); } if (subData.HasTrigger) { recordTypes.Add(subData.TriggeringRecordTypes); } } else if (field is DictType dict) { switch (dict.Mode) { case DictMode.KeyedValue: { if (!dict.ValueTypeGen.TryGetFieldData(out var subData)) { continue; } if (!subData.HasTrigger) { continue; } recordTypes.Add(subData.TriggeringRecordTypes); break; } case DictMode.KeyValue: { if (dict.KeyTypeGen.TryGetFieldData(out var subData) && subData.HasTrigger) { recordTypes.Add(subData.TriggeringRecordTypes); } if (dict.ValueTypeGen.TryGetFieldData(out subData) && subData.HasTrigger) { recordTypes.Add(subData.TriggeringRecordTypes); } break; } default: throw new NotImplementedException(); } } else if (field is GenderedType gendered) { if (gendered.MaleMarker.HasValue) { recordTypes.Add(gendered.MaleMarker.Value); recordTypes.Add(gendered.FemaleMarker.Value); } var subData = gendered.SubTypeGeneration.GetFieldData(); if (subData.RecordType != null) { recordTypes.Add(subData.RecordType.Value); } } } foreach (var item in recordTypes) { yield return(item); } }
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(); } } }
protected override void FillPublicElement(ObjectGeneration obj, FileGeneration fg) { using (var args = new FunctionWrapper(fg, $"public static void FillPublicElement{ModuleNickname}")) { args.Add($"{obj.Interface(getter: false, internalInterface: true)} item"); args.Add($"XElement {XmlTranslationModule.XElementLine.GetParameterName(obj)}"); args.Add("string name"); args.Add($"ErrorMaskBuilder? errorMask"); args.Add($"{nameof(TranslationCrystal)}? translationMask"); } using (new BraceWrapper(fg)) { fg.AppendLine("switch (name)"); using (new BraceWrapper(fg)) { bool isInRange = false; foreach (var field in obj.IterateFields(expandSets: SetMarkerType.ExpandSets.FalseAndInclude, nonIntegrated: true)) { if (field is DataType set) { foreach (var subField in set.IterateFieldsWithMeta()) { if (subField.Field.Derivative) { continue; } if (subField.Field.ReadOnly) { continue; } if (!subField.Field.IntegrateField) { continue; } if (!this.TryGetTypeGeneration(subField.Field.GetType(), out var generator)) { throw new ArgumentException("Unsupported type generator: " + subField.Field); } fg.AppendLine($"case \"{subField.Field.Name}\":"); using (new DepthWrapper(fg)) { if (generator.ShouldGenerateCopyIn(subField.Field)) { generator.GenerateCopyIn( fg: fg, objGen: obj, typeGen: subField.Field, nodeAccessor: XmlTranslationModule.XElementLine.GetParameterName(obj).Result, itemAccessor: Accessor.FromType(subField.Field, "item"), translationMaskAccessor: "translationMask", errorMaskAccessor: $"errorMask"); } HandleDataTypeParsing(obj, fg, set, subField, ref isInRange); fg.AppendLine("break;"); } } } else if (field.IntegrateField) { if (field.Derivative) { continue; } if (field.ReadOnly) { continue; } if (!this.TryGetTypeGeneration(field.GetType(), out var generator)) { throw new ArgumentException("Unsupported type generator: " + field); } fg.AppendLine($"case \"{field.Name}\":"); using (new DepthWrapper(fg)) { if (generator.ShouldGenerateCopyIn(field)) { generator.GenerateCopyIn( fg: fg, objGen: obj, typeGen: field, nodeAccessor: XmlTranslationModule.XElementLine.GetParameterName(obj).Result, itemAccessor: Accessor.FromType(field, "item"), translationMaskAccessor: "translationMask", errorMaskAccessor: $"errorMask"); } fg.AppendLine("break;"); } } } fg.AppendLine("default:"); using (new DepthWrapper(fg)) { if (obj.HasLoquiBaseObject) { using (var args = new ArgsWrapper(fg, $"{this.TranslationCreateClass(obj.BaseClass)}.FillPublicElement{ModuleNickname}")) { args.Add("item: item"); args.Add($"{XmlTranslationModule.XElementLine.GetParameterName(obj)}: {XmlTranslationModule.XElementLine.GetParameterName(obj)}"); args.Add("name: name"); args.Add("errorMask: errorMask"); if (this.TranslationMaskParameter) { args.Add($"translationMask: translationMask"); } } } fg.AppendLine("break;"); } } } fg.AppendLine(); }
public override void GenerateWriteToNode(ObjectGeneration obj, FileGeneration fg) { using (var args = new FunctionWrapper(fg, $"public static void WriteToNode{ModuleNickname}{obj.GetGenericTypes(MaskType.Normal)}")) { args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.IGetter, defs: obj.Generics)); args.Add($"{obj.Interface(internalInterface: true, getter: true)} item"); args.Add($"XElement {XmlTranslationModule.XElementLine.GetParameterName(obj)}"); args.Add($"ErrorMaskBuilder? errorMask"); args.Add($"{nameof(TranslationCrystal)}? translationMask"); } using (new BraceWrapper(fg)) { if (obj.HasLoquiBaseObject) { using (var args = new ArgsWrapper(fg, $"{this.TranslationWriteClass(obj.BaseClass)}.WriteToNode{ModuleNickname}")) { args.Add($"item: item"); args.Add($"{XmlTranslationModule.XElementLine.GetParameterName(obj)}: {XmlTranslationModule.XElementLine.GetParameterName(obj)}"); args.Add($"errorMask: errorMask"); args.Add($"translationMask: translationMask"); } } void generateNormal(XmlTranslationGeneration generator, TypeGeneration field) { if (!generator.ShouldGenerateWrite(field)) { return; } List <string> conditions = new List <string>(); if (field.HasBeenSet) { conditions.Add($"{field.HasBeenSetAccessor(getter: true, accessor: Accessor.FromType(field, "item"))}"); } if (this.TranslationMaskParameter) { conditions.Add(field.GetTranslationIfAccessor("translationMask")); } if (conditions.Count > 0) { using (var args = new IfWrapper(fg, ANDs: true)) { foreach (var item in conditions) { args.Add(item); } } } using (new BraceWrapper(fg, doIt: conditions.Count > 0)) { var maskType = this.Gen.MaskModule.GetMaskModule(field.GetType()).GetErrorMaskTypeStr(field); generator.GenerateWrite( fg: fg, objGen: obj, typeGen: field, writerAccessor: $"{XmlTranslationModule.XElementLine.GetParameterName(obj)}", itemAccessor: Accessor.FromType(field, "item"), errorMaskAccessor: $"errorMask", translationMaskAccessor: "translationMask", nameAccessor: $"nameof(item.{field.Name})"); } } foreach (var field in obj.IterateFields(expandSets: SetMarkerType.ExpandSets.FalseAndInclude, nonIntegrated: true)) { if (!this.TryGetTypeGeneration(field.GetType(), out var generator)) { if (!field.IntegrateField) { continue; } throw new ArgumentException("Unsupported type generator: " + field); } if (field is DataType dataType) { if (dataType.HasBeenSet) { fg.AppendLine($"if (item.{dataType.StateName}.HasFlag({obj.Name}.{dataType.EnumName}.Has))"); } using (new BraceWrapper(fg, doIt: dataType.HasBeenSet)) { bool isInRange = false; int encounteredBreakIndex = 0; foreach (var subField in dataType.IterateFieldsWithMeta()) { if (!this.TryGetTypeGeneration(subField.Field.GetType(), out var subGenerator)) { throw new ArgumentException("Unsupported type generator: " + subField.Field); } var subData = subField.Field.GetFieldData(); if (!subGenerator.ShouldGenerateCopyIn(subField.Field)) { continue; } if (subField.BreakIndex != -1) { fg.AppendLine($"if (!item.{dataType.StateName}.HasFlag({obj.Name}.{dataType.EnumName}.Break{subField.BreakIndex}))"); fg.AppendLine("{"); fg.Depth++; encounteredBreakIndex++; } if (subField.Range != null && !isInRange) { isInRange = true; fg.AppendLine($"if (item.{dataType.StateName}.HasFlag({obj.Name}.{dataType.EnumName}.Range{subField.RangeIndex}))"); fg.AppendLine("{"); fg.Depth++; } if (subField.Range == null && isInRange) { isInRange = false; fg.Depth--; fg.AppendLine("}"); } generateNormal(subGenerator, subField.Field); } for (int i = 0; i < encounteredBreakIndex; i++) { fg.Depth--; fg.AppendLine("}"); if (i == encounteredBreakIndex - 1) { fg.AppendLine("else"); using (new BraceWrapper(fg)) { fg.AppendLine($"node.Add(new XElement(\"Has{dataType.EnumName}\"));"); } } } } } else { generateNormal(generator, field); } } } fg.AppendLine(); }