Example #1
0
        public string sig()
        {
            string sig = access.ToString().ToLower() + " ";

            if (type == MethodType.StaticFunction || type == MethodType.Extension)
            {
                sig += "static ";
            }
            if (type == MethodType.Abstract)
            {
                sig += "abstract ";
            }
            else if (type == MethodType.Override)
            {
                sig += "override ";
            }
            else if (type == MethodType.Virtual)
            {
                sig += "virtual ";
            }

            if (async)
            {
                sig += "async ";
            }

            sig += $"{(returnType != null ? returnType.RealName(true) : "")} {name}{(genericSuffix.Valid() ? $"{genericSuffix}" : "")}";

            var funcFirstArg = type == MethodType.Extension ? $"this {classType.RealName(true)} self" : "";

            sig += $"({CodeGenTools.MergeSig(funcFirstArg, args)}) {constraints}";

            return(sig);
        }
Example #2
0
        public void Commit(Action <string> sink)
        {
            if (doNotGen)
            {
                return;
            }

            //if (stubMode && (type == MethodType.Override || (classBuilder.name == "SerializationExtensions"))) return;
            if (stubMode && (type == MethodType.Override))
            {
                return;
            }

            var indent = "";

            if (classBuilder.namespaceName.Valid())
            {
                indent = ("\t\t");
            }
            else
            {
                indent = ("\t");
            }

            sink(indent + sig());
            sink($"{indent}{{");
            if (!stubMode)
            {
                if (isDebug)
                {
                    sink("#if !RELEASE");
                }
                if (needBaseValCall && !doNotCallBaseMethod)
                {
                    if (returnType != typeof(void))
                    {
                        sink($"{indent}\tvar baseVal = base.{RemoveBaseIfNeeded(name)}({CodeGenTools.ExtranctArgNames(args)});");
                    }
                    else
                    {
                        sink($"{indent}\tbase.{RemoveBaseIfNeeded(name)}({CodeGenTools.ExtranctArgNames(args)});");
                    }
                }
                sink(builder.ToStringWithoutListLineEnd());
                if (isDebug)
                {
                    sink("#else");
                    sink($"{indent}\tthrow new HackCommandExecutionOnReleaseBuild();");
                    sink("#endif");
                }
            }
            else
            {
                sink(indent + "\tthrow new NotImplementedException();");
            }

            sink($"{indent}}}");
        }
        static void GenerateConstructionFromRoot(Type type)
        {
            var rootType = type.FindTagInHierarchy <RootType>()?.type;

            if (rootType == null)
            {
                return;
            }

            Action <MethodBuilder> fillCreateWithLivableSetup = sink =>
            {
                sink.content($"inst.root = this;");
//                if (type.HasReferenceId())
//                    sink.content($"inst.Id = entityIdFactory++;");
                //if (type.HasNestedLivableChildren())
                sink.content($"inst.{SetupHierarchyFuncName}();");
                sink.content($"inst.{SetupChildrenIdFuncName}();");
                //if (type.HasChildrenThatNeedsRootSetup())
            };

            var constructorMethodFlags = BindingFlags.DeclaredOnly | BindingFlags.Instance
                                         | BindingFlags.Public | BindingFlags.NonPublic;

            if (type.IsAbstract == false && (!type.IsGenericType || type.IsConstructedGenericType))
            {
                bool hasConstructor = false;
                foreach (var methodInfo in type.GetMethods(constructorMethodFlags))
                {
                    if (methodInfo.Name.StartsWith("Ctor"))
                    {
                        var sig = methodInfo.GetParameters().Select(p => $"{p.ParameterType.RealName(true)} {p.Name}")
                                  .PrintCollection();
                        var call = methodInfo.GetParameters().Select(p => p.Name).PrintCollection();
                        // ctor mwthod found
                        var constructFull = GenClassSink(rootType).Method(type.CreateLivableInRootFunc(), rootType, MethodType.Instance, type, sig, "", "");
                        constructFull.indent++;
                        //constructFull.content($"var inst = pool.{type.GetFromPoolFunc()}();");
                        CreateNewInstance(constructFull, new DataInfo {
                            type = type, baseAccess = "inst", sureIsNull = true
                        }, "", true, "", true);
                        fillCreateWithLivableSetup(constructFull);

                        constructFull.content($"inst.{methodInfo.Name}({call});");
                        constructFull.content($"return inst;");
                        hasConstructor = true;
                    }
                }

                if (!hasConstructor)
                {
                    var createWithSetup = GenClassSink(rootType).Method(type.CreateLivableInRootFunc(), rootType, MethodType.Instance, type, "", "", "");
                    createWithSetup.indent++;
                    CreateNewInstance(createWithSetup, new DataInfo {
                        type = type, baseAccess = "inst", sureIsNull = true
                    }, "", true, "", true);
                    fillCreateWithLivableSetup(createWithSetup);
                    createWithSetup.content($"return inst;");
                }
            }

            // Create from prototype
            if ((type.ReadGenFlags() & GenTaskFlags.UpdateFrom) != 0)
            {
                var createFromProrotype = GenClassSink(rootType).Method(type.CreateLivableInRootFunc(), rootType, MethodType.Instance, type, $"{type.RealName(true)} prototype", "", "");
                createFromProrotype.indent++;
                //CreateNewInstance(createFromProrotype, new DataInfo{type = type, baseAccess = "inst", sureIsNull = true}, "", true, "", true );
                //createFromProrotype.content($"var inst = ({type.RealName(true)})prototype.NewInst();");
                GenUpdateValueFromInstance(createFromProrotype, new DataInfo {
                    type = type, baseAccess = $"inst", sureIsNull = true
                }, "prototype", false, needCreateVar: true);
                fillCreateWithLivableSetup(createFromProrotype);
                createFromProrotype.content($"return inst;");
            }

            if (polymorphicRootNodes.ContainsKey(type))
            {
                MethodInfo polymorphicConstructor = null;
                foreach (var methodInfo in type.GetMethods(constructorMethodFlags))
                {
                    if (methodInfo.Name.StartsWith("Prepare") && (methodInfo.IsVirtual || methodInfo.IsAbstract))
                    {
                        var sig = methodInfo.GetParameters().Select(p => $"{p.ParameterType.RealName(true)} {p.Name}")
                                  .PrintCollection();
                        var enumTypeRef = type.PolymorphicRootTypeEnumName();
                        if (string.IsNullOrEmpty(type.Namespace) == false)
                        {
                            enumTypeRef = type.Namespace + "." + enumTypeRef;
                        }
                        sig = CodeGenTools.MergeSig($"{enumTypeRef} classId", sig);
                        var call = methodInfo.GetParameters().Select(p => p.Name).PrintCollection();
                        // ctor mwthod found
                        var constructFull = GenClassSink(rootType).Method($"CreatePolymorphic{type.UniqueName(false)}",
                                                                          rootType, MethodType.Instance, type, sig, "", "");
                        constructFull.indent++;
                        constructFull.content($"var inst = {type.NewPolymorphicFromClassIdExpression(type.NeedsPooledPolymorphConstruction())};");
                        fillCreateWithLivableSetup(constructFull);
                        constructFull.content($"inst.{methodInfo.Name}({call});");
                        constructFull.content($"return inst;");
                    }
                }
            }
        }
Example #4
0
        public static void CreateNewInstance(MethodBuilder sink, DataInfo info, string classIdReader, bool pooled,
                                             string refInst, bool needCreateVar, bool wrapType = false)
        {
            // Some bullshit logic here
            // All of this because of value wrapper concept that should be reconsidered
            var t    = wrapType ? info.realType : info.type;
            var name = wrapType ? info.accessPrefix + info.baseAccess : info.access;

            string newExpr  = "";
            bool   needCast = false;

            if (t == typeof(string))
            {
                newExpr = "string.Empty";
            }
            else if (t.IsArray)
            {
                newExpr = $"Array.Empty<{t.RealName(true).Remove(t.RealName(true).Length - 2)}>()";
            }
            else if (t.CanBeAncestor() && info.cantBeAncestor == false)
            {
                needCast = true;
                if (CodeGenTools.Valid(refInst))
                {
                    string poolArg = "";
                    if (t.HasPool() && pooled)
                    {
                        poolArg = "pool";
                    }
                    newExpr = $"{refInst}.{PolymorphNewInstOfSameType}({poolArg})";
                }
                else
                {
                    if (CodeGenTools.Valid(classIdReader) == false)
                    {
                        if (t.IsAbstract)
                        {
                            return;
                        }
                        newExpr = NewInstExpr(t, pooled);
                    }
                    else
                    {
                        var staticTypeCreator = baseClassMap.GetOrDefault(t, t).RealName(true);
                        if (t.IsGenericParameter)
                        {
                            if (t.GetGenericParameterConstraints().TryFind(par => !par.IsInterface, out var hardPar))
                            {
                                staticTypeCreator = hardPar.RealName(true);
                            }
                            else
                            {
                                Error($"can't generate new instance construction for unknown type {t} in {info.carrierType}, constrain this type with some base class like DataNode");
                            }
                        }
                        newExpr = $"{staticTypeCreator}.{PolymorphInstanceFuncName}({classIdReader})";
                    }
                }
            }
            else
            {
createNormally:
                if (t.IsAbstract)
                {
                    Error($"Type {t} is abstract but required to have constructor during {sink.classBuilder.name} generation");
                    return;
                }
                newExpr = NewInstExpr(t, pooled, info.defaultValue);
            }

            sink.content($"{(needCreateVar ? "var " : "")}{name} = {(needCast ? $"({t.RealName(true)})" : "")}{newExpr};");
        }
Example #5
0
 public void content(string source)
 {
     contentBuilder.AppendLine(CodeGenTools.Indent(indent) + source);
 }
Example #6
0
        static void GenerateFieldWrappers()
        {
            Dictionary <string, List <__GenReplaceFieldBase> > fieldsCodeReplace =
                new Dictionary <string, List <__GenReplaceFieldBase> >();

            foreach (var typePair in typeGenRequested)
            {
                var type = typePair.Key;

                bool updateEvent = type.HasAttribute <GenUpdatedEvent>();
                //if (type.IsGameNode() == false && !type.IsDataRoot() && !updateEvent) continue;

                var sink = GenClassSink(type);

                if (updateEvent)
                {
                    sink.inheritance("IHasUpdateEvent");
                    sink.content("[GenIgnore] EventStream updated = new EventStream();");
                    sink.content("public IEventReader Updated => updated;");
                }

                Action <Type, string, int, bool, bool> genField = (fType, fName, index, reactive, recordable) =>
                {
                    var recordInteraction = "";
                    var updateInteraction = updateEvent ? "updated.Send();" : "";
                    if (reactive)
                    {
                        sink.usingSink("ZergRush.ReactiveCore");
                        var cellName = $"{fName}Cell";
                        sink.content(
                            $"[GenIgnore] public Cell<{fType.RealName(true)}> {cellName} = new Cell<{fType.RealName(true)}>();");
                        sink.content(
                            $"{fType.RealName(true)} _{fName} {{ get {{ return {cellName}.value; }} set {{ {cellName}.value = value; {recordInteraction} {updateInteraction}}} }}");
                    }
                    else
                    {
                        var backingFieldName = $"__{fName}";
                        sink.content($"[GenIgnore] public {fType.RealName(true)} {backingFieldName};");
                        sink.content(
                            $"{fType.RealName(true)} _{fName} {{ get {{ return {backingFieldName}; }} set {{ {backingFieldName} = value; {recordInteraction} {updateInteraction}}} }}");
                    }
                };
                int fieldIndex = 0;
                foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.NonPublic |
                                                     BindingFlags.Instance))
                {
                    if (field.HasAttribute <GenUICell>() || field.HasAttribute <GenRecordable>())
                    {
                        fieldIndex++;
                        var tag = (__GenReplaceFieldBase)field.GetAttributeIfAny <GenUICell>() ??
                                  field.GetAttributeIfAny <GenRecordable>();
                        tag.type = field.FieldType;
                        tag.name = field.Name;
                        fieldsCodeReplace.TryGetOrNew(type.RealName()).Add(tag);
                        genField(field.FieldType, field.Name, fieldIndex, field.HasAttribute <GenUICell>(),
                                 field.HasAttribute <GenRecordable>());
                    }
                }

                foreach (var field in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic |
                                                         BindingFlags.Instance))
                {
                    if (field.HasAttribute <GenInclude>() == false)
                    {
                        continue;
                    }
                    if (field.HasAttribute <GenUICell>() || field.HasAttribute <GenRecordable>())
                    {
                        fieldIndex++;
                        genField(field.PropertyType, field.Name, fieldIndex, field.HasAttribute <GenUICell>(),
                                 field.HasAttribute <GenRecordable>());
                    }
                }
            }

            if (fieldsCodeReplace.Count > 0)
            {
                foreach (var info in fieldsCodeReplace)
                {
                    Debug.Log($"Type: {info.Key} Field to replace: {info.Value.Select(i => i.name).PrintCollection()}");
                    var filePath = info.Value[0].file;
                    Debug.Log($"Type: {info.Key} filePath: {filePath}");

                    var allText = File.ReadAllLines(filePath);

                    foreach (var field in info.Value)
                    {
                        var tagLine = allText[field.line - 1];
                        tagLine = tagLine + "[GenInclude]";
                        allText[field.line - 1] = tagLine;

                        var targetLine = allText[field.line];
                        Debug.Log($"replacing " + targetLine);
                        var isPublic         = targetLine.Contains("public") ? "public" : "";
                        var backingFieldName = "_" + field.name;
                        var whiteSpaceCount  = 0;
                        ConsumeSpaces(ref whiteSpaceCount, targetLine);
                        targetLine = CodeGenTools.Indent(whiteSpaceCount / 4) +
                                     $"{isPublic} {field.type.RealName(true)} {field.name} {{ get {{ return {backingFieldName}; }} set {{ {backingFieldName} = value;}} }}";
                        Debug.Log(targetLine);
                        allText[field.line] = targetLine;
                    }

                    File.WriteAllLines(filePath, allText);
                }
            }
        }
Example #7
0
 public void content(string str)
 {
     builder.Append(CodeGenTools.Indent(indent + classBuilder.indent));
     builder.AppendLine(str);
 }
Example #8
0
        public static void GeneralReadFrom(MethodBuilder sink, DataInfo info,
                                           Action <MethodBuilder, DataInfo> baseReadCall, string isNullReader, string classIdReader,
                                           string directReader, string refInst, string refIdReader, bool pooled, Func <Type, string> configIdReader = null, bool needCreateVar = false,
                                           bool useTempVarThenAssign = false, bool getDataNodeFromRootWithRefId = false)
        {
            var t         = info.type;
            var canBeNull = info.canBeNull && !t.IsValueType;

            var    originalInfo = info;
            string tempVar      = "__" + originalInfo.baseAccess.Replace("[", "").Replace("]", "");

            if (useTempVarThenAssign)
            {
                sink.content($"var {tempVar} = {originalInfo.access};");
                info = new DataInfo
                {
                    type       = originalInfo.type,
                    baseAccess = tempVar,
                };
            }

            var  name          = info.access;
            bool newInstCalled = false;

            if (needCreateVar)
            {
                sink.content($"{info.type.RealName(true)} {info.name} = default;");
            }

            if (t.IsImmutableValueType() || t.IsValueType && t.IsControllable() == false)
            {
                sink.content($"{name} = {directReader};");
                return;
            }
            else if (t.IsRef())
            {
                if (CodeGenTools.Valid(refIdReader))
                {
                    sink.content($"{info.access}.id = {refIdReader};");
                }
                else
                {
                    throw new NotImplementedException();
                }
            }
            else
            {
                if (canBeNull)
                {
                    sink.content($"if ({isNullReader}) {{");
                    sink.indent++;
                    SinkRemovePostProcess(sink, info, pooled);
                    sink.content($"{name} = null;");
                    sink.indent--;
                    sink.content($"}}");
                    sink.content($"else {{ ");
                    sink.indent++;
                }

                bool fromExternalSource = false;
                if (t.IsConfig() && info.insideConfigStorage == false)
                {
                    ConfigFromId(sink, info, configIdReader, false);
                    fromExternalSource = true;
                }
                else if (getDataNodeFromRootWithRefId && typeof(IReferencableFromDataRoot).IsAssignableFrom(t))
                {
                    sink.content($"{info.access} = ({info.type.RealName(true)})root.Recall({refIdReader});");
                    fromExternalSource = true;
                }
                else
                {
                    if (info.sureIsNull && !info.type.IsValueType)
                    {
                        CreateNewInstance(sink, info, classIdReader, pooled, refInst, false);
                        newInstCalled = true;
                    }
                    else
                    {
                        string createNewCondition = "";
                        if (canBeNull || info.CanBeNullAfterConstruction())
                        {
                            createNewCondition = $"{name} == null";
                        }

                        string classIdVarName = $"{name.Replace('[', '_').Replace(']', '_').Replace('.', '_')}ClassId";
                        if (t.CanBeAncestor() && info.cantBeAncestor == false)
                        {
                            sink.content($"var {classIdVarName} = {classIdReader};");
                            createNewCondition = AddOrCondition(createNewCondition,
                                                                $"{name}.{PolymorphClassIdGetter} != {classIdVarName}");
                        }
                        if (info.type.IsImmutableType() == false && CodeGenTools.Valid(createNewCondition))
                        {
                            sink.content($"if ({createNewCondition}) {{");
                            sink.indent++;
                            SinkRemovePostProcess(sink, info, pooled);
                            CreateNewInstance(sink, info, classIdVarName, pooled, refInst, false);
                            newInstCalled = true;
                            sink.indent--;
                            sink.content($"}}");
                        }
                    }
                }

                if (!fromExternalSource)
                {
                    baseReadCall(sink, info);
                }

                if (canBeNull)
                {
                    sink.indent--;
                    sink.content($"}}");
                }
            }

            if (useTempVarThenAssign)
            {
                sink.content($"{originalInfo.access} = {tempVar};");
            }
        }
Example #9
0
 public void content(string source)
 {
     classContent.AppendLine(CodeGenTools.Indent(indent) + source);
 }