示例#1
0
        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;
            }
        }
示例#2
0
        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);
         }
     }
 }
示例#5
0
 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);
         }
     }
 }
示例#7
0
 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);
 }
示例#9
0
 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};");
         }
     }
 }
示例#10
0
 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);
     }
 }
示例#11
0
        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;
                        }
                    }
                }
            }
        }
示例#12
0
 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);
                 }
             }
         }
     }
 }
示例#13
0
        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);
            }
        }
示例#14
0
 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);
 }
示例#15
0
        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);
        }
示例#16
0
        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();
        }
示例#17
0
        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);
        }
示例#18
0
        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);
        }
示例#19
0
        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))");
                        }
示例#20
0
        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);
        }
示例#21
0
        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})");
                            }
示例#22
0
        private void GenerateWriteParallel(ObjectGeneration obj, FileGeneration fg)
        {
            LoquiType groupInstance     = null;
            LoquiType listGroupInstance = null;
            var       objData           = obj.GetObjectData();

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

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

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

            if (groupInstance != null)
            {
                using (var args = new FunctionWrapper(fg,
                                                      $"public static void WriteGroupParallel<T>"))
                {
                    args.Add("IGroupGetter<T> group");
                    args.Add($"{nameof(MasterReferenceReader)} masters");
                    args.Add("int targetIndex");
                    if (objData.GameReleaseOptions != null)
                    {
                        args.Add($"{nameof(GameConstants)} gameConstants");
                    }
                    args.Add("Stream[] streamDepositArray");
                    if (objData.UsesStringFiles)
                    {
                        args.Add($"{nameof(StringsWriter)}? stringsWriter");
                    }
                    args.Wheres.AddRange(groupInstance.TargetObjectGeneration.GenerateWhereClauses(LoquiInterfaceType.IGetter, groupInstance.TargetObjectGeneration.Generics));
                }
                using (new BraceWrapper(fg))
                {
                    string gameConstantsStr;
                    if (objData.GameReleaseOptions == null)
                    {
                        gameConstantsStr = $"{nameof(GameConstants)}.{obj.GetObjectData().GameCategory}";
                    }
                    else
                    {
                        gameConstantsStr = "gameConstants";
                    }
                    fg.AppendLine("if (group.RecordCache.Count == 0) return;");
                    fg.AppendLine($"var cuts = group.Cut(CutCount).ToArray();");
                    fg.AppendLine($"Stream[] subStreams = new Stream[cuts.Length + 1];");
                    fg.AppendLine($"byte[] groupBytes = new byte[{gameConstantsStr}.GroupConstants.HeaderLength];");
                    fg.AppendLine($"BinaryPrimitives.WriteInt32LittleEndian(groupBytes.AsSpan(), RecordTypes.GRUP.TypeInt);");
                    fg.AppendLine($"var groupByteStream = new MemoryStream(groupBytes);");
                    fg.AppendLine($"using (var stream = new MutagenWriter(groupByteStream, {gameConstantsStr}, dispose: false))");
                    using (new BraceWrapper(fg))
                    {
                        fg.AppendLine($"stream.Position += 8;");
                        fg.AppendLine($"GroupBinaryWriteTranslation.WriteEmbedded<T>(group, stream);");
                    }
                    fg.AppendLine($"subStreams[0] = groupByteStream;");
                    fg.AppendLine($"Parallel.ForEach(cuts, (cutItems, state, counter) =>");
                    using (new BraceWrapper(fg)
                    {
                        AppendSemicolon = true, AppendParenthesis = true
                    })
                    {
                        fg.AppendLine($"{nameof(MemoryTributary)} trib = new {nameof(MemoryTributary)}();");
                        fg.AppendLine($"var bundle = new {nameof(WritingBundle)}({gameConstantsStr})");
                        using (var prop = new PropertyCtorWrapper(fg))
                        {
                            prop.Add($"{nameof(WritingBundle.MasterReferences)} = masters");
                            if (objData.UsesStringFiles)
                            {
                                prop.Add($"{nameof(WritingBundle.StringsWriter)} = stringsWriter");
                            }
                        }
                        fg.AppendLine($"using (var stream = new MutagenWriter(trib, bundle, dispose: false))");
                        using (new BraceWrapper(fg))
                        {
                            fg.AppendLine($"foreach (var item in cutItems)");
                            using (new BraceWrapper(fg))
                            {
                                fg.AppendLine($"item.WriteToBinary(stream);");
                            }
                        }
                        fg.AppendLine($"subStreams[(int)counter + 1] = trib;");
                    }
                    fg.AppendLine($"UtilityTranslation.CompileSetGroupLength(subStreams, groupBytes);");
                    fg.AppendLine($"streamDepositArray[targetIndex] = new CompositeReadStream(subStreams, resetPositions: true);");
                }
                fg.AppendLine();
            }
        }
示例#23
0
        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);
                    }
                }
            }
        }
示例#24
0
        public override async Task GenerateInClass(ObjectGeneration obj, FileGeneration fg)
        {
            if (obj.GetObjectData().ObjectType != ObjectType.Mod)
            {
                return;
            }
            var objData = obj.GetObjectData();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                        using (var args = new FunctionWrapper(fg,
                                                              $"public static {ReleaseEnumName(obj)} To{ReleaseEnumName(obj)}"))
                        {
                            args.Add($"this {nameof(GameRelease)} release");
                        }
                        using (new BraceWrapper(fg))
                        {
                            fg.AppendLine("return release switch");
                            using (new BraceWrapper(fg)
                            {
                                AppendSemicolon = true
                            })
                            {
                                using (var comma = new CommaWrapper(fg))
                                {
                                    foreach (var item in objData.GameReleaseOptions)
                                    {
                                        comma.Add($"{nameof(GameRelease)}.{item} => {ReleaseEnumName(obj)}.{item}");
                                    }
                                    comma.Add("_ => throw new ArgumentException()");
                                }
                            }
                        }
                    }
                }
            }
        }
        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;");
            }
        }
示例#27
0
        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();
                }
            }
        }
示例#29
0
        protected override void FillPublicElement(ObjectGeneration obj, FileGeneration fg)
        {
            using (var args = new FunctionWrapper(fg,
                                                  $"public static void FillPublicElement{ModuleNickname}"))
            {
                args.Add($"{obj.Interface(getter: false, internalInterface: true)} item");
                args.Add($"XElement {XmlTranslationModule.XElementLine.GetParameterName(obj)}");
                args.Add("string name");
                args.Add($"ErrorMaskBuilder? errorMask");
                args.Add($"{nameof(TranslationCrystal)}? translationMask");
            }
            using (new BraceWrapper(fg))
            {
                fg.AppendLine("switch (name)");
                using (new BraceWrapper(fg))
                {
                    bool isInRange = false;
                    foreach (var field in obj.IterateFields(expandSets: SetMarkerType.ExpandSets.FalseAndInclude, nonIntegrated: true))
                    {
                        if (field is DataType set)
                        {
                            foreach (var subField in set.IterateFieldsWithMeta())
                            {
                                if (subField.Field.Derivative)
                                {
                                    continue;
                                }
                                if (subField.Field.ReadOnly)
                                {
                                    continue;
                                }
                                if (!subField.Field.IntegrateField)
                                {
                                    continue;
                                }
                                if (!this.TryGetTypeGeneration(subField.Field.GetType(), out var generator))
                                {
                                    throw new ArgumentException("Unsupported type generator: " + subField.Field);
                                }

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

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

                    fg.AppendLine("default:");
                    using (new DepthWrapper(fg))
                    {
                        if (obj.HasLoquiBaseObject)
                        {
                            using (var args = new ArgsWrapper(fg,
                                                              $"{this.TranslationCreateClass(obj.BaseClass)}.FillPublicElement{ModuleNickname}"))
                            {
                                args.Add("item: item");
                                args.Add($"{XmlTranslationModule.XElementLine.GetParameterName(obj)}: {XmlTranslationModule.XElementLine.GetParameterName(obj)}");
                                args.Add("name: name");
                                args.Add("errorMask: errorMask");
                                if (this.TranslationMaskParameter)
                                {
                                    args.Add($"translationMask: translationMask");
                                }
                            }
                        }
                        fg.AppendLine("break;");
                    }
                }
            }
            fg.AppendLine();
        }
示例#30
0
        public override void GenerateWriteToNode(ObjectGeneration obj, FileGeneration fg)
        {
            using (var args = new FunctionWrapper(fg,
                                                  $"public static void WriteToNode{ModuleNickname}{obj.GetGenericTypes(MaskType.Normal)}"))
            {
                args.Wheres.AddRange(obj.GenerateWhereClauses(LoquiInterfaceType.IGetter, defs: obj.Generics));
                args.Add($"{obj.Interface(internalInterface: true, getter: true)} item");
                args.Add($"XElement {XmlTranslationModule.XElementLine.GetParameterName(obj)}");
                args.Add($"ErrorMaskBuilder? errorMask");
                args.Add($"{nameof(TranslationCrystal)}? translationMask");
            }
            using (new BraceWrapper(fg))
            {
                if (obj.HasLoquiBaseObject)
                {
                    using (var args = new ArgsWrapper(fg,
                                                      $"{this.TranslationWriteClass(obj.BaseClass)}.WriteToNode{ModuleNickname}"))
                    {
                        args.Add($"item: item");
                        args.Add($"{XmlTranslationModule.XElementLine.GetParameterName(obj)}: {XmlTranslationModule.XElementLine.GetParameterName(obj)}");
                        args.Add($"errorMask: errorMask");
                        args.Add($"translationMask: translationMask");
                    }
                }

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

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

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

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

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

                                var subData = subField.Field.GetFieldData();
                                if (!subGenerator.ShouldGenerateCopyIn(subField.Field))
                                {
                                    continue;
                                }
                                if (subField.BreakIndex != -1)
                                {
                                    fg.AppendLine($"if (!item.{dataType.StateName}.HasFlag({obj.Name}.{dataType.EnumName}.Break{subField.BreakIndex}))");
                                    fg.AppendLine("{");
                                    fg.Depth++;
                                    encounteredBreakIndex++;
                                }
                                if (subField.Range != null && !isInRange)
                                {
                                    isInRange = true;
                                    fg.AppendLine($"if (item.{dataType.StateName}.HasFlag({obj.Name}.{dataType.EnumName}.Range{subField.RangeIndex}))");
                                    fg.AppendLine("{");
                                    fg.Depth++;
                                }
                                if (subField.Range == null && isInRange)
                                {
                                    isInRange = false;
                                    fg.Depth--;
                                    fg.AppendLine("}");
                                }
                                generateNormal(subGenerator, subField.Field);
                            }
                            for (int i = 0; i < encounteredBreakIndex; i++)
                            {
                                fg.Depth--;
                                fg.AppendLine("}");
                                if (i == encounteredBreakIndex - 1)
                                {
                                    fg.AppendLine("else");
                                    using (new BraceWrapper(fg))
                                    {
                                        fg.AppendLine($"node.Add(new XElement(\"Has{dataType.EnumName}\"));");
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        generateNormal(generator, field);
                    }
                }
            }
            fg.AppendLine();
        }