private void DecompileStates() { ProcessDescriptor pd = (ProcessDescriptor)_code; _templ = new MSILDecompilerTemplate() { Instance = pd.Instance.Owner, ArgumentValues = new object[0], Decompilee = _code, Method = _code.Method, Code = MethodCode.Create(_code.Method), DisallowReturnStatements = true, NestLoopsDeeply = true, TryToEliminateLoops = true, DisallowConditionals = true }; LocalVariableState initialState = _templ.ExportLocalVariableState(); GetStateInfo(_dissectionPoints[0], initialState); while (_stateWorkQueue.Any()) { StateInfo si = _stateWorkQueue.Dequeue(); MSILDecompiler decomp = new MSILDecompiler(_code, si.CFG, _instance) { Template = _templ }; _templ.AddAttribute(this); _templ.ImportLocalVariableState(si.LVState); IDecompilationResult result = decomp.Decompile(); si.StateFun = result.Decompiled; _calledMethods.AddRange(result.CalledMethods); _referencedFields.AddRange(result.ReferencedFields); } }
private void GenerateForArray(ContainerDefinition containerDefinition) { Type type = containerDefinition.Type; Type elementType = type.GetElementType(); bool flag = this.CheckIfPrimitiveOrPrimiteHolderStruct(elementType); TypeDefinition structDefinition = this._definitionContext.GetStructDefinition(elementType); if (!(elementType != typeof(object))) { return; } MethodCode methodCode = new MethodCode(); methodCode.IsStatic = true; methodCode.AccessModifier = MethodCodeAccessModifier.Private; methodCode.Name = "AutoGeneratedStaticCollectObjectsForArray" + (object)this._containerNumber; methodCode.MethodSignature = "(object o, global::System.Collections.Generic.List<object> collectedObjects)"; if (flag) { methodCode.AddLine("//Got no child, type: " + type.FullName); } else if (structDefinition != null) { string str1 = elementType.FullName.Replace('+', '.'); string str2 = type.FullName.Replace('+', '.'); methodCode.AddLine("var target = (global::" + str2 + ")o;"); methodCode.AddLine(""); methodCode.AddLine("for (int i = 0; i < target.Length; i++)"); methodCode.AddLine("{"); methodCode.AddLine("var element = target[i];"); methodCode.AddLine(""); methodCode.AddLine("global::" + str1 + ".AutoGeneratedStaticCollectObjects" + elementType.Name + "(element, collectedObjects);"); methodCode.AddLine("}"); } else { methodCode.AddLine("var target = (global::System.Array)o;"); methodCode.AddLine(""); methodCode.AddLine("for (int i = 0; i < target.Length; i++)"); methodCode.AddLine("{"); methodCode.AddLine("var element = target.GetValue(i);"); methodCode.AddLine("collectedObjects.Add(element);"); methodCode.AddLine("}"); } SaveId saveId = containerDefinition.SaveId; StringWriter stringWriter1 = new StringWriter(); StringWriter stringWriter2 = stringWriter1; saveId.WriteTo((IWriter)stringWriter2); string str = flag ? "true" : "false"; this._managerMethod.AddLine("var saveId" + (object)this._delegateCount + " = global::TaleWorlds.SaveSystem.Definition.SaveId.ReadSaveIdFrom(new global::TaleWorlds.Library.StringReader(\"" + stringWriter1.Data + "\"));"); this._managerMethod.AddLine("var typeDefinition" + (object)this._delegateCount + " = (global::TaleWorlds.SaveSystem.Definition.ContainerDefinition)definitionContext.TryGetTypeDefinition(saveId" + (object)this._delegateCount + ");"); this._managerMethod.AddLine("TaleWorlds.SaveSystem.Definition.CollectObjectsDelegate d" + (object)this._delegateCount + " = " + methodCode.Name + ";"); this._managerMethod.AddLine("typeDefinition" + (object)this._delegateCount + ".InitializeForAutoGeneration(d" + (object)this._delegateCount + ", " + str + ");"); this._managerMethod.AddLine(""); ++this._delegateCount; this._managerClass.AddMethod(methodCode); ++this._containerNumber; }
private void GenerateForQueue(ContainerDefinition containerDefinition) { Type type = containerDefinition.Type; if (!this.CheckIfPrimitiveOrPrimiteHolderStruct(type.GetGenericArguments()[0])) { return; } MethodCode methodCode = new MethodCode(); methodCode.IsStatic = true; methodCode.AccessModifier = MethodCodeAccessModifier.Private; methodCode.Name = "AutoGeneratedStaticCollectObjectsForQueue" + (object)this._containerNumber; methodCode.MethodSignature = "(object o, global::System.Collections.Generic.List<object> collectedObjects)"; methodCode.AddLine("//Got no child, type: " + type.FullName); SaveId saveId = containerDefinition.SaveId; StringWriter stringWriter1 = new StringWriter(); StringWriter stringWriter2 = stringWriter1; saveId.WriteTo((IWriter)stringWriter2); this._managerMethod.AddLine("var saveId" + (object)this._delegateCount + " = global::TaleWorlds.SaveSystem.Definition.SaveId.ReadSaveIdFrom(new global::TaleWorlds.Library.StringReader(\"" + stringWriter1.Data + "\"));"); this._managerMethod.AddLine("var typeDefinition" + (object)this._delegateCount + " = (global::TaleWorlds.SaveSystem.Definition.ContainerDefinition)definitionContext.TryGetTypeDefinition(saveId" + (object)this._delegateCount + ");"); this._managerMethod.AddLine("TaleWorlds.SaveSystem.Definition.CollectObjectsDelegate d" + (object)this._delegateCount + " = " + methodCode.Name + ";"); this._managerMethod.AddLine("typeDefinition" + (object)this._delegateCount + ".InitializeForAutoGeneration(d" + (object)this._delegateCount + ", true);"); this._managerMethod.AddLine(""); ++this._delegateCount; this._managerClass.AddMethod(methodCode); ++this._containerNumber; }
public FSMTransformerTemplate(DesignContext ctx, CodeDescriptor code, object instance, object[] arguments) { _context = ctx; _code = code; _instance = instance; _arguments = arguments; _methodCode = MethodCode.Create(_code.Method); }
/// <summary> /// Constructs a new instance based on a control-flow graph and an assumption on IsCompleted properties. /// </summary> /// <param name="cfg">a control-flow graph</param> /// <param name="assumption">whether the IsCompleted property is assumed to return always true or always false</param> public AsyncMethodCustomInstructionInfo(MethodCode cfg, EAssumption assumption): base(cfg.Method) { _cfg = cfg; _assumption = assumption; _branchOverrides = new Dictionary<int, int>(); MarkIsCompletedBranches(); }
public void Generate() { NamespaceCode orCreateNamespace = this._codeGenerationContext.FindOrCreateNamespace(this.DefaultNamespace); ClassCode classCode = new ClassCode(); classCode.AccessModifier = ClassCodeAccessModifier.Internal; classCode.Name = "AutoGeneratedSaveManager"; classCode.AddInterface("global::TaleWorlds.SaveSystem.Definition.IAutoGeneratedSaveManager"); MethodCode methodCode = new MethodCode(); methodCode.IsStatic = false; methodCode.AccessModifier = MethodCodeAccessModifier.Public; methodCode.Name = "Initialize"; methodCode.MethodSignature = "(global::TaleWorlds.SaveSystem.Definition.DefinitionContext definitionContext)"; classCode.AddMethod(methodCode); this._managerMethod = methodCode; this._managerClass = classCode; ClassCode clasCode = classCode; orCreateNamespace.AddClass(clasCode); foreach (TypeDefinition definition in this._definitions) { this.GenerateForClassOrStruct(definition); } foreach (TypeDefinition structDefinition in this._structDefinitions) { this.GenerateForClassOrStruct(structDefinition); } foreach (ContainerDefinition containerDefinition in this._containerDefinitions) { ContainerType containerType; if (containerDefinition.Type.IsContainer(out containerType)) { switch (containerType) { case ContainerType.List: this.GenerateForList(containerDefinition); continue; case ContainerType.Dictionary: this.GenerateForDictionary(containerDefinition); continue; case ContainerType.Array: this.GenerateForArray(containerDefinition); continue; case ContainerType.Queue: this.GenerateForQueue(containerDefinition); continue; default: continue; } } } }
public MethodCode CreateMethod(string name) { if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } var mthdCode = new MethodCode(this, name); _methodCodes.Add(mthdCode); return(mthdCode); }
private void fixLocalVars(Hashtable hash, MethodCode methodCode) { if (methodCode.locVarBaseTypes != null) { for (int i = 0; i < methodCode.locVarBaseTypes.Length; i++) { methodCode.locVarBaseTypes[i] = formType( hash, methodCode.locVarBaseTypes[i], methodCode.locVarDeclarators[i] ); } } }
private void InitCoState(TAVerb tav, CoStateInfo csi) { MethodCode csc = MethodCode.Create(tav.Op.Method); MethodDescriptor md = new MethodDescriptor(tav.Op.Method, new object[0], new EVariability[0]); MSILDecompiler decomp = new MSILDecompiler(md, csc, tav.Op.Target); decomp.Template.DisallowReturnStatements = true; decomp.Template.NestLoopsDeeply = true; decomp.Template.TryToEliminateLoops = true; decomp.Template.DisallowConditionals = true; IDecompilationResult result = decomp.Decompile(); csi.StateAction = result.Decompiled; csi.DuringAction = tav.During; }
/// <summary> /// Executes the analysis. /// </summary> public virtual void Run() { Contract.Requires(!AnalysisDone); Contract.Ensures(AnalysisDone); MethodFacts myFacts = FactUniverse.Instance.GetFacts(Method); CFG = myFacts.CFG; _stackStates = new AbstractStackState <TElem> [CFG.Instructions.Count]; AbstractStackState <TElem> initial = CreateInitialStackState(); Queue <Tuple <AbstractStackState <TElem>, ILInstruction> > q = new Queue <Tuple <AbstractStackState <TElem>, ILInstruction> >(); q.Enqueue(Tuple.Create(initial, CFG.Instructions[0])); int marshal = CFG.Instructions.Count - 1; while (q.Count > 0) { Tuple <AbstractStackState <TElem>, ILInstruction> cur = q.Dequeue(); AbstractStackState <TElem> preState = cur.Item1; ILInstruction ili = cur.Item2; AbstractStackState <TElem> nextState = Propagate(ili, preState); ILInstruction[] succs = CFG.GetSuccessorsOf(ili); if (_stackStates[ili.Index] == null) { _stackStates[ili.Index] = nextState; } else { bool changed = Merge(_stackStates[ili.Index], nextState, out _stackStates[ili.Index]); if (!changed) { continue; } } foreach (ILInstruction nextILI in succs) { if (nextILI.Index < marshal) // skip pseudo ret at the end { q.Enqueue(Tuple.Create(_stackStates[ili.Index], nextILI)); } } } AnalysisDone = true; }
public static DissectResult Dissect(MethodBase mb) { MethodBodyReader mbr = new MethodBodyReader(mb); WaitDissector wd = new WaitDissector(mbr.instructions); wd.Dissect(); EnsureNotInitBehavior(mbr.instructions, wd.DissectionPoints[0], mb.Name); List <MethodCode> states = new List <MethodCode>(); HashSet <int> exits = new HashSet <int>(wd.DissectionPoints); foreach (int ilIndex in wd.DissectionPoints) { MethodCode mc = MethodCode.Create(mb, ilIndex + 1, exits); states.Add(mc); } return(new DissectResult(states, wd.DissectionPoints)); }
private void InitializeCFGs() { _cfg = MethodCode.Create(_code.Method); _stateTargets = StateTargetFinder.FindStateTargets(_cfg); var cii = new AsyncMethodCustomInstructionInfo( _cfg, ImplStyle == EAsyncImplStyle.FSM ? AsyncMethodCustomInstructionInfo.EAssumption.NeverCompleted : AsyncMethodCustomInstructionInfo.EAssumption.AlwaysCompleted); _stateCFGs = _stateTargets.Select(t => new MethodCode(cii, t.StartIndex)).ToArray(); }
public IDecompilationResult DecompileSequential() { _cfg = MethodCode.Create(_code.Method); var targets = StateTargetFinder.FindStateTargets(_cfg); var entry = targets[0]; var entryCFG = MethodCode.Create(_code.Method, entry.StartIndex); var decomp = new MSILDecompiler(_code, entryCFG, _fsmInstance); decomp.Template.AddAttribute(this); decomp.Template.DisallowReturnStatements = true; var result = decomp.Decompile(); return result; }
/// <summary> /// Determines the set of CIL instructions which potentially compute a particular stack element. /// </summary> /// <param name="ilIndex">index of CIL instruction</param> /// <param name="stackLevel">index of stack element (0 is top)</param> /// <param name="cfg">control-flow graph</param> /// <returns>indices of CIL instructions which come into consideration for producing specified stack element</returns> public static IEnumerable<int> GetStackElementDefinitions(int ilIndex, int stackLevel, MethodCode cfg) { Queue<Tuple<int, int>> q = new Queue<Tuple<int, int>>(); bool[] visited = new bool[cfg.Instructions.Count]; foreach (ILInstruction pred in cfg.GetPredecessors(ilIndex)) { q.Enqueue(Tuple.Create(pred.Index, stackLevel)); } while (q.Count > 0) { Tuple<int, int> cur = q.Dequeue(); int curIndex = cur.Item1; int curLevel = cur.Item2; visited[curIndex] = true; int npush, npop; GetStackBilance(cfg.Instructions[curIndex], cfg.Method, out npop, out npush); if (npush + curLevel >= 1) { yield return curIndex; } else { int delta = npush - npop; int nextLevel = curLevel + delta; if (nextLevel > 0) throw new InvalidOperationException("Illegal stack behavior detected in method " + cfg.Method); foreach (ILInstruction pred in cfg.GetPredecessors(curIndex)) { if (!visited[pred.Index]) q.Enqueue(Tuple.Create(pred.Index, nextLevel)); } } } }
private void GenerateForDictionary(ContainerDefinition containerDefinition) { Type type = containerDefinition.Type; Type genericArgument1 = type.GetGenericArguments()[0]; Type genericArgument2 = type.GetGenericArguments()[1]; int num = this.CheckIfPrimitiveOrPrimiteHolderStruct(genericArgument1) ? 1 : 0; bool flag1 = this.CheckIfPrimitiveOrPrimiteHolderStruct(genericArgument2); TypeDefinition structDefinition1 = this._definitionContext.GetStructDefinition(genericArgument1); TypeDefinition structDefinition2 = this._definitionContext.GetStructDefinition(genericArgument2); bool flag2 = (num & (flag1 ? 1 : 0)) != 0; if (num == 0 && structDefinition1 == null || !flag1 && structDefinition2 == null || (!(genericArgument1 != typeof(object)) || !(genericArgument2 != typeof(object)))) { return; } MethodCode methodCode = new MethodCode(); methodCode.IsStatic = true; methodCode.AccessModifier = MethodCodeAccessModifier.Private; methodCode.Name = "AutoGeneratedStaticCollectObjectsForDictionary" + (object)this._containerNumber; methodCode.MethodSignature = "(object o, global::System.Collections.Generic.List<object> collectedObjects)"; if (flag2) { methodCode.AddLine("//Got no child, type: " + type.FullName); } else { methodCode.AddLine("var target = (global::System.Collections.IDictionary)o;"); methodCode.AddLine(""); if (structDefinition1 != null) { string str = genericArgument1.FullName.Replace('+', '.'); methodCode.AddLine("foreach (var key in target.Keys)"); methodCode.AddLine("{"); methodCode.AddLine("global::" + str + ".AutoGeneratedStaticCollectObjects" + genericArgument1.Name + "(key, collectedObjects);"); methodCode.AddLine("}"); } methodCode.AddLine(""); if (structDefinition2 != null) { string str = genericArgument2.FullName.Replace('+', '.'); methodCode.AddLine("foreach (var value in target.Values)"); methodCode.AddLine("{"); methodCode.AddLine("global::" + str + ".AutoGeneratedStaticCollectObjects" + genericArgument2.Name + "(value, collectedObjects);"); methodCode.AddLine("}"); } } SaveId saveId = containerDefinition.SaveId; StringWriter stringWriter1 = new StringWriter(); StringWriter stringWriter2 = stringWriter1; saveId.WriteTo((IWriter)stringWriter2); string str1 = flag2 ? "true" : "false"; this._managerMethod.AddLine("var saveId" + (object)this._delegateCount + " = global::TaleWorlds.SaveSystem.Definition.SaveId.ReadSaveIdFrom(new global::TaleWorlds.Library.StringReader(\"" + stringWriter1.Data + "\"));"); this._managerMethod.AddLine("var typeDefinition" + (object)this._delegateCount + " = (global::TaleWorlds.SaveSystem.Definition.ContainerDefinition)definitionContext.TryGetTypeDefinition(saveId" + (object)this._delegateCount + ");"); this._managerMethod.AddLine("TaleWorlds.SaveSystem.Definition.CollectObjectsDelegate d" + (object)this._delegateCount + " = " + methodCode.Name + ";"); this._managerMethod.AddLine("typeDefinition" + (object)this._delegateCount + ".InitializeForAutoGeneration(d" + (object)this._delegateCount + ", " + str1 + ");"); this._managerMethod.AddLine(""); ++this._delegateCount; this._managerClass.AddMethod(methodCode); ++this._containerNumber; }
/// <summary> /// Determines the set of CIL instructions which potentially compute a particular stack element. /// </summary> /// <param name="ilIndex">index of CIL instruction</param> /// <param name="stackLevel">index of stack element (0 is top)</param> /// <param name="cfg">control-flow graph</param> /// <returns>indices of CIL instructions which come into consideration for producing specified stack element</returns> public static IEnumerable <int> GetStackElementDefinitions(int ilIndex, int stackLevel, MethodCode cfg) { Queue <Tuple <int, int> > q = new Queue <Tuple <int, int> >(); bool[] visited = new bool[cfg.Instructions.Count]; foreach (ILInstruction pred in cfg.GetPredecessors(ilIndex)) { q.Enqueue(Tuple.Create(pred.Index, stackLevel)); } while (q.Count > 0) { Tuple <int, int> cur = q.Dequeue(); int curIndex = cur.Item1; int curLevel = cur.Item2; visited[curIndex] = true; int npush, npop; GetStackBilance(cfg.Instructions[curIndex], cfg.Method, out npop, out npush); if (npush + curLevel >= 1) { yield return(curIndex); } else { int delta = npush - npop; int nextLevel = curLevel + delta; if (nextLevel > 0) { throw new InvalidOperationException("Illegal stack behavior detected in method " + cfg.Method); } foreach (ILInstruction pred in cfg.GetPredecessors(curIndex)) { if (!visited[pred.Index]) { q.Enqueue(Tuple.Create(pred.Index, nextLevel)); } } } } }
/// <summary> /// Given a control-flow graph of an asynchronous method, finds all state entry points. /// This is done using some pattern matching and knowledge on how the compiler translates asynchronous methods. /// Therefore, some special cases might not be resolved correctly, and the code might break down with future compiler revisions. /// </summary> /// <param name="cfg">a control-flow graph</param> /// <returns>all state entry points</returns> public static MSILCodeBlock[] FindStateTargets(MethodCode cfg) { var entry = cfg.BasicBlocks[0]; FieldInfo statefield = null; int stateLocalIndex = -1; int stateValue = int.MinValue; int stateOffset = 0; var mode = EStateLocMode.LocatingStateField; var q = new Queue<Tuple<int, MSILCodeBlock>>(); foreach (var cili in entry.Range) { switch (mode) { case EStateLocMode.LocatingStateField: if (cili.Code == OpCodes.Ldfld) { // this must be the state field statefield = (FieldInfo)cili.Operand; mode = EStateLocMode.LocatingStateLocal; } break; case EStateLocMode.LocatingStateLocal: { int index; if (IsStloc(cili, out index)) stateLocalIndex = index; } break; } int value; if (IsLdc_I(cili, out value)) { stateValue = value; } if (cili.Code == OpCodes.Sub) { stateOffset = stateValue; } else if (cili.Code == OpCodes.Beq || cili.Code == OpCodes.Beq_S) { // State -3 exists only in debug builds and skips the whole FSM => irrelevant if (stateValue != -3) { q.Enqueue(Tuple.Create(stateValue, entry.Successors[1])); } q.Enqueue(Tuple.Create(-1, entry.Successors[0])); } else if (cili.Code == OpCodes.Switch) { bool have_1 = false; for (int i = 1; i < entry.Successors.Length; i++) { int state = i - 1 + stateOffset; // State -3 exists only in debug builds and skips the whole FSM => irrelevant // State -2 is completion state => also irrelevant if (state >= -1) { q.Enqueue(Tuple.Create(state, entry.Successors[i])); if (state == -1) have_1 = true; } } if (!have_1) q.Enqueue(Tuple.Create(-1, entry.Successors[0])); } } var stateDic = new SortedDictionary<int, MSILCodeBlock>(); while (q.Any()) { var tup = q.Dequeue(); int state = tup.Item1; var block = tup.Item2; int value; if (IsLdloc(block.Range.First(), out value) && value == stateLocalIndex) { if (block.Range.Count != 3) throw new NotSupportedException("Decompilation of await pattern failed: expected 3 instructions in this block."); if (!IsLdc_I(block.Range[1], out stateValue)) throw new NotSupportedException("Decompilation of await pattern failed: expected Ldc_I<x> op-code."); if (block.Range[2].Code != OpCodes.Beq && block.Range[2].Code != OpCodes.Beq_S) throw new NotSupportedException("Decompilation of await pattern failed: expected Beq/Beq_S op-code."); q.Enqueue(Tuple.Create(stateValue, block.Successors[1])); q.Enqueue(Tuple.Create(-1, block.Successors[0])); } else { stateDic[state] = block; } } for (int state = -1; state < stateDic.Count - 1; state++) { if (!stateDic.ContainsKey(state)) throw new NotSupportedException("Decompilation of await pattern failed: expected consecutive states from -1 to " + (stateDic.Count-1)); } return stateDic.Values.ToArray(); }
private void GenerateForClassOrStruct(TypeDefinition typeDefinition) { Type type1 = typeDefinition.Type; bool isClass = type1.IsClass; bool flag1 = !isClass; bool flag2 = this.CheckIfBaseTypeDefind(type1); string name1 = type1.Namespace; string str1 = type1.FullName.Replace('+', '.'); string fullClassName = str1.Substring(name1.Length + 1, str1.Length - name1.Length - 1).Replace('+', '.'); string[] nestedClasses = this.GetNestedClasses(fullClassName); NamespaceCode orCreateNamespace = this._codeGenerationContext.FindOrCreateNamespace(name1); string str2 = nestedClasses[nestedClasses.Length - 1]; ClassCode classCode = (ClassCode)null; for (int index = 0; index < nestedClasses.Length; ++index) { string className = nestedClasses[index]; ClassCode clasCode = new ClassCode(); clasCode.IsPartial = true; if (index + 1 == nestedClasses.Length) { clasCode.IsClass = isClass; } clasCode.AccessModifier = ClassCodeAccessModifier.DoNotMention; int genericInformation = this.GetClassGenericInformation(className); if (genericInformation >= 0) { clasCode.IsGeneric = true; clasCode.GenericTypeCount = genericInformation; className = className.Substring(0, className.Length - 2); } clasCode.Name = className; if (classCode != null) { classCode.AddNestedClass(clasCode); } else { orCreateNamespace.AddClass(clasCode); } classCode = clasCode; } TypeSaveId saveId = (TypeSaveId)typeDefinition.SaveId; int delegateCount = this._delegateCount; ++this._delegateCount; this._managerMethod.AddLine("var typeDefinition" + (object)delegateCount + " = (global::TaleWorlds.SaveSystem.Definition.TypeDefinition)definitionContext.TryGetTypeDefinition(new global::TaleWorlds.SaveSystem.Definition.TypeSaveId(" + (object)saveId.Id + "));"); if (!type1.IsGenericTypeDefinition && !type1.IsAbstract) { MethodCode methodCode = new MethodCode(); methodCode.IsStatic = true; methodCode.AccessModifier = flag1 ? MethodCodeAccessModifier.Public : MethodCodeAccessModifier.Internal; methodCode.Name = "AutoGeneratedStaticCollectObjects" + str2; methodCode.MethodSignature = "(object o, global::System.Collections.Generic.List<object> collectedObjects)"; methodCode.AddLine("var target = (global::" + str1 + ")o;"); methodCode.AddLine("target.AutoGeneratedInstanceCollectObjects(collectedObjects);"); classCode.AddMethod(methodCode); this._managerMethod.AddLine("TaleWorlds.SaveSystem.Definition.CollectObjectsDelegate d" + (object)delegateCount + " = global::" + name1 + "." + fullClassName + "." + methodCode.Name + ";"); this._managerMethod.AddLine(nameof(typeDefinition) + (object)delegateCount + ".InitializeForAutoGeneration(d" + (object)delegateCount + ");"); } this._managerMethod.AddLine(""); MethodCode methodCode1 = new MethodCode(); if (flag2) { methodCode1.PolymorphismInfo = MethodCodePolymorphismInfo.Override; methodCode1.AccessModifier = MethodCodeAccessModifier.Protected; } else if (!type1.IsSealed) { methodCode1.PolymorphismInfo = MethodCodePolymorphismInfo.Virtual; methodCode1.AccessModifier = MethodCodeAccessModifier.Protected; } else { methodCode1.PolymorphismInfo = MethodCodePolymorphismInfo.None; methodCode1.AccessModifier = MethodCodeAccessModifier.Private; } methodCode1.Name = "AutoGeneratedInstanceCollectObjects"; methodCode1.MethodSignature = "(global::System.Collections.Generic.List<object> collectedObjects)"; if (flag2) { methodCode1.AddLine("base.AutoGeneratedInstanceCollectObjects(collectedObjects);"); methodCode1.AddLine(""); } foreach (MemberDefinition memberDefinition in typeDefinition.MemberDefinitions) { if (memberDefinition is FieldDefinition) { FieldInfo fieldInfo = (memberDefinition as FieldDefinition).FieldInfo; Type fieldType = fieldInfo.FieldType; string name2 = fieldInfo.Name; if (fieldType.IsClass || fieldType.IsInterface) { if (fieldType != typeof(string)) { bool flag3 = false; Type declaringType = fieldInfo.DeclaringType; if (declaringType != type1) { flag3 = this.CheckIfTypeDefined(declaringType); } string str3 = ""; if (flag3) { str3 += "//"; } string line = str3 + "collectedObjects.Add(this." + name2 + ");"; methodCode1.AddLine(line); } } else if (!fieldType.IsClass && this._definitionContext.GetStructDefinition(fieldType) != null) { string str3 = ""; bool flag3 = false; Type declaringType = fieldInfo.DeclaringType; if (declaringType != type1) { flag3 = this.CheckIfTypeDefined(declaringType); } if (flag3) { str3 += "//"; } string str4 = fieldType.FullName.Replace('+', '.'); string line = str3 + "global::" + str4 + ".AutoGeneratedStaticCollectObjects" + fieldType.Name + "(this." + name2 + ", collectedObjects);"; methodCode1.AddLine(line); } } } methodCode1.AddLine(""); foreach (MemberDefinition memberDefinition in typeDefinition.MemberDefinitions) { if (memberDefinition is PropertyDefinition) { PropertyDefinition propertyDefinition = memberDefinition as PropertyDefinition; PropertyInfo propertyInfo = propertyDefinition.PropertyInfo; Type propertyType = propertyDefinition.PropertyInfo.PropertyType; string name2 = propertyInfo.Name; if (propertyType.IsClass || propertyType.IsInterface) { if (propertyType != typeof(string)) { bool flag3 = false; Type declaringType = propertyInfo.DeclaringType; if (declaringType != type1) { flag3 = this.CheckIfTypeDefined(declaringType); } string str3 = ""; if (flag3) { str3 += "//"; } string line = str3 + "collectedObjects.Add(this." + name2 + ");"; methodCode1.AddLine(line); } } else if (!propertyType.IsClass && this._definitionContext.GetStructDefinition(propertyType) != null) { bool flag3 = false; Type declaringType = propertyInfo.DeclaringType; if (declaringType != type1) { flag3 = this.CheckIfTypeDefined(declaringType); } string str3 = ""; if (flag3) { str3 += "//"; } string str4 = propertyType.FullName.Replace('+', '.'); string line = str3 + "global::" + str4 + ".AutoGeneratedStaticCollectObjects" + propertyType.Name + "(this." + name2 + ", collectedObjects);"; methodCode1.AddLine(line); } } } classCode.AddMethod(methodCode1); foreach (MemberDefinition memberDefinition in typeDefinition.MemberDefinitions) { if (!type1.IsGenericTypeDefinition) { MethodCode methodCode2 = new MethodCode(); string str3 = ""; Type type2 = (Type)null; switch (memberDefinition) { case PropertyDefinition _: PropertyDefinition propertyDefinition = memberDefinition as PropertyDefinition; str3 = propertyDefinition.PropertyInfo.Name; type2 = propertyDefinition.PropertyInfo.DeclaringType; break; case FieldDefinition _: FieldDefinition fieldDefinition = memberDefinition as FieldDefinition; str3 = fieldDefinition.FieldInfo.Name; type2 = fieldDefinition.FieldInfo.DeclaringType; break; } bool flag3 = false; if (type2 != type1) { flag3 = this.CheckIfTypeDefined(type2); } if (!flag3) { methodCode2.Name = "AutoGeneratedGetMemberValue" + str3; methodCode2.MethodSignature = "(object o)"; methodCode2.IsStatic = true; methodCode2.AccessModifier = MethodCodeAccessModifier.Internal; methodCode2.PolymorphismInfo = MethodCodePolymorphismInfo.None; methodCode2.ReturnParameter = "object"; methodCode2.AddLine("var target = (global::" + str1 + ")o;"); methodCode2.AddLine("return (object)target." + str3 + ";"); classCode.AddMethod(methodCode2); string str4 = "GetPropertyDefinitionWithId"; if (memberDefinition is FieldDefinition) { str4 = "GetFieldDefinitionWithId"; } this._managerMethod.AddLine("{"); this._managerMethod.AddLine("var memberDefinition = typeDefinition" + (object)delegateCount + "." + str4 + "(new global::TaleWorlds.SaveSystem.Definition.MemberTypeId(" + (object)memberDefinition.Id.TypeLevel + "," + (object)memberDefinition.Id.LocalSaveId + "));"); this._managerMethod.AddLine("memberDefinition.InitializeForAutoGeneration(" + ("global::" + name1 + "." + fullClassName + "." + methodCode2.Name) + ");"); this._managerMethod.AddLine("}"); this._managerMethod.AddLine(""); } } } }