// 收集所有 字段,属性,方法
        public void Collect()
        {
            var bindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static;
            var fields       = type.GetFields(bindingFlags);

            foreach (var field in fields)
            {
                if (field.IsSpecialName)
                {
                    bindingManager.Info("skip special field: {0}", field.Name);
                    continue;
                }
                if (field.FieldType.IsPointer)
                {
                    bindingManager.Info("skip pointer field: {0}", field.Name);
                    continue;
                }
                if (field.IsDefined(typeof(JSOmitAttribute), false))
                {
                    bindingManager.Info("skip omitted field: {0}", field.Name);
                    continue;
                }
                if (field.IsDefined(typeof(ObsoleteAttribute), false))
                {
                    bindingManager.Info("skip obsolete field: {0}", field.Name);
                    continue;
                }
                if (transform != null && transform.IsMemberBlocked(field.Name))
                {
                    bindingManager.Info("skip blocked field: {0}", field.Name);
                    continue;
                }
                AddField(field);
            }
            var events = type.GetEvents(bindingFlags);

            foreach (var evt in events)
            {
                if (evt.IsSpecialName)
                {
                    bindingManager.Info("skip special event: {0}", evt.Name);
                    continue;
                }
                if (evt.EventHandlerType.IsPointer)
                {
                    bindingManager.Info("skip pointer event: {0}", evt.Name);
                    continue;
                }
                if (evt.IsDefined(typeof(ObsoleteAttribute), false))
                {
                    bindingManager.Info("skip obsolete event: {0}", evt.Name);
                    continue;
                }
                if (evt.IsDefined(typeof(JSOmitAttribute), false))
                {
                    bindingManager.Info("skip omitted event: {0}", evt.Name);
                    continue;
                }
                if (transform != null && transform.IsMemberBlocked(evt.Name))
                {
                    bindingManager.Info("skip blocked event: {0}", evt.Name);
                    continue;
                }
                AddEvent(evt);
            }
            var properties = type.GetProperties(bindingFlags);

            foreach (var property in properties)
            {
                if (property.IsSpecialName)
                {
                    bindingManager.Info("skip special property: {0}", property.Name);
                    continue;
                }
                if (property.PropertyType.IsPointer)
                {
                    bindingManager.Info("skip pointer property: {0}", property.Name);
                    continue;
                }
                if (property.IsDefined(typeof(JSOmitAttribute), false))
                {
                    bindingManager.Info("skip omitted property: {0}", property.Name);
                    continue;
                }
                if (property.IsDefined(typeof(ObsoleteAttribute), false))
                {
                    bindingManager.Info("skip obsolete property: {0}", property.Name);
                    continue;
                }
                if (transform != null && transform.IsMemberBlocked(property.Name))
                {
                    bindingManager.Info("skip blocked property: {0}", property.Name);
                    continue;
                }
                //TODO: 索引访问
                if (property.Name == "Item")
                {
                    if (property.CanRead && property.GetMethod != null)
                    {
                        if (BindingManager.IsUnsupported(property.GetMethod))
                        {
                            bindingManager.Info("skip unsupported get-method: {0}", property.GetMethod);
                            continue;
                        }
                        AddMethod(property.GetMethod, true, "$GetValue");
                    }
                    if (property.CanWrite && property.SetMethod != null)
                    {
                        if (BindingManager.IsUnsupported(property.SetMethod))
                        {
                            bindingManager.Info("skip unsupported set-method: {0}", property.SetMethod);
                            continue;
                        }
                        AddMethod(property.SetMethod, true, "$SetValue");
                    }
                    // bindingManager.Info("skip indexer property: {0}", property.Name);
                    continue;
                }
                AddProperty(property);
            }
            if (!type.IsAbstract)
            {
                var constructors = type.GetConstructors();
                foreach (var constructor in constructors)
                {
                    if (constructor.IsDefined(typeof(JSOmitAttribute), false))
                    {
                        bindingManager.Info("skip omitted constructor: {0}", constructor);
                        continue;
                    }
                    if (constructor.IsDefined(typeof(ObsoleteAttribute), false))
                    {
                        bindingManager.Info("skip obsolete constructor: {0}", constructor);
                        continue;
                    }
                    if (BindingManager.ContainsPointer(constructor))
                    {
                        bindingManager.Info("skip pointer constructor: {0}", constructor);
                        continue;
                    }
                    AddConstructor(constructor);
                }
            }
            var methods = type.GetMethods(bindingFlags);

            foreach (var method in methods)
            {
                if (BindingManager.IsGenericMethod(method))
                {
                    bindingManager.Info("skip generic method: {0}", method);
                    continue;
                }
                if (BindingManager.ContainsPointer(method))
                {
                    bindingManager.Info("skip unsafe (pointer) method: {0}", method);
                    continue;
                }
                if (method.IsSpecialName)
                {
                    bindingManager.Info("skip special method: {0}", method);
                    continue;
                }
                if (method.IsDefined(typeof(JSOmitAttribute), false))
                {
                    bindingManager.Info("skip omitted method: {0}", method);
                    continue;
                }
                if (method.IsDefined(typeof(ObsoleteAttribute), false))
                {
                    bindingManager.Info("skip obsolete method: {0}", method);
                    continue;
                }
                if (transform != null && transform.IsMemberBlocked(method.Name))
                {
                    bindingManager.Info("skip blocked method: {0}", method.Name);
                    continue;
                }
                // if (IsPropertyMethod(method))
                // {
                //     continue;
                // }
                do
                {
                    if (IsExtensionMethod(method))
                    {
                        var targetType = method.GetParameters()[0].ParameterType;
                        var targetInfo = bindingManager.GetExportedType(targetType);
                        if (targetInfo != null)
                        {
                            targetInfo.AddMethod(method);
                            break;
                        }
                        // else fallthrough (as normal static method)
                    }
                    AddMethod(method);
                } while (false);
            }
        }
Esempio n. 2
0
        public override void Dispose()
        {
            using (new PreservedCodeGen(cg))
            {
                using (new RegFuncCodeGen(cg))
                {
                    using (new RegFuncNamespaceCodeGen(cg, bindingInfo))
                    {
                        var constructor = bindingInfo.constructors.available ? bindingInfo.constructors.name : "object_private_ctor";
                        if (!bindingInfo.constructors.available && !bindingInfo.type.IsAbstract)
                        {
                            if (bindingInfo.type.IsSubclassOf(typeof(Component)))
                            {
                                // 因为 ts 泛型约束需要 new() 形式, 所以在定义中产生一个 public 定义
                                // 例如: GetComponent<T extends Component>(type: { new(): T }): T
                                cg.tsDeclare.AppendLine("/*protected*/ constructor()");
                            }
                            else
                            {
                                cg.tsDeclare.AppendLine("protected constructor()");
                            }
                        }
                        cg.cs.AppendLine("duk_begin_class(ctx, \"{0}\", typeof({1}), {2});",
                                         bindingInfo.jsName,
                                         this.cg.bindingManager.GetCSTypeFullName(bindingInfo.type),
                                         constructor);
                        foreach (var kv in bindingInfo.methods)
                        {
                            var    regName  = kv.Value.regName;
                            var    funcName = kv.Value.name;
                            var    bStatic  = false;
                            string redirect;
                            if (this.bindingInfo.transform != null && this.bindingInfo.transform.TryRedirectMethod(regName, out redirect))
                            {
                                funcName = redirect;
                            }
                            cg.cs.AppendLine("duk_add_method(ctx, \"{0}\", {1}, {2});", regName, funcName, bStatic ? -2 : -1);
                        }
                        foreach (var kv in bindingInfo.staticMethods)
                        {
                            var    regName  = kv.Value.regName;
                            var    funcName = kv.Value.name;
                            var    bStatic  = true;
                            string redirect;
                            if (this.bindingInfo.transform != null && this.bindingInfo.transform.TryRedirectMethod(regName, out redirect))
                            {
                                funcName = redirect;
                            }
                            cg.cs.AppendLine("duk_add_method(ctx, \"{0}\", {1}, {2});", regName, funcName, bStatic ? -2 : -1);
                        }
                        foreach (var kv in bindingInfo.properties)
                        {
                            var bindingInfo = kv.Value;
                            if (bindingInfo.staticPair.IsValid())
                            {
                                var tsPropertyVar = BindingManager.GetTSVariable(bindingInfo.regName);
                                cg.cs.AppendLine("duk_add_property(ctx, \"{0}\", {1}, {2}, {3});",
                                                 tsPropertyVar,
                                                 bindingInfo.staticPair.getterName != null ? bindingInfo.staticPair.getterName : "null",
                                                 bindingInfo.staticPair.setterName != null ? bindingInfo.staticPair.setterName : "null",
                                                 -2);

                                var tsPropertyPrefix = "static ";
                                if (bindingInfo.staticPair.setterName == null)
                                {
                                    tsPropertyPrefix += "readonly ";
                                }
                                var tsPropertyType = this.cg.bindingManager.GetTSTypeFullName(bindingInfo.propertyInfo.PropertyType);
                                cg.tsDeclare.AppendLine($"{tsPropertyPrefix}{tsPropertyVar}: {tsPropertyType}");
                            }
                            if (bindingInfo.instancePair.IsValid())
                            {
                                var tsPropertyVar = BindingManager.GetTSVariable(bindingInfo.regName);
                                cg.cs.AppendLine("duk_add_property(ctx, \"{0}\", {1}, {2}, {3});",
                                                 tsPropertyVar,
                                                 bindingInfo.instancePair.getterName != null ? bindingInfo.instancePair.getterName : "null",
                                                 bindingInfo.instancePair.setterName != null ? bindingInfo.instancePair.setterName : "null",
                                                 -1);

                                var tsPropertyPrefix = "";
                                if (bindingInfo.instancePair.setterName == null)
                                {
                                    tsPropertyPrefix += "readonly ";
                                }
                                var tsPropertyType = this.cg.bindingManager.GetTSTypeFullName(bindingInfo.propertyInfo.PropertyType);
                                cg.tsDeclare.AppendLine($"{tsPropertyPrefix}{tsPropertyVar}: {tsPropertyType}");
                            }
                        }
                        foreach (var kv in bindingInfo.fields)
                        {
                            var bindingInfo = kv.Value;
                            var bStatic     = bindingInfo.isStatic;
                            var tsFieldVar  = BindingManager.GetTSVariable(bindingInfo.regName);
                            if (bindingInfo.constantValue != null)
                            {
                                var cv = bindingInfo.constantValue;
                                cg.cs.AppendLine($"duk_add_const(ctx, \"{tsFieldVar}\", {cv}, {-2});");
                            }
                            else
                            {
                                cg.cs.AppendLine("duk_add_field(ctx, \"{0}\", {1}, {2}, {3});",
                                                 tsFieldVar,
                                                 bindingInfo.getterName != null ? bindingInfo.getterName : "null",
                                                 bindingInfo.setterName != null ? bindingInfo.setterName : "null",
                                                 bStatic ? -2 : -1);
                            }
                            var tsFieldPrefix = bStatic ? "static " : "";
                            if (bindingInfo.setterName == null)
                            {
                                tsFieldPrefix += "readonly ";
                            }
                            var tsFieldType = this.cg.bindingManager.GetTSTypeFullName(bindingInfo.fieldInfo.FieldType);
                            cg.tsDeclare.AppendLine($"{tsFieldPrefix}{tsFieldVar}: {tsFieldType}");
                        }
                        foreach (var kv in bindingInfo.events)
                        {
                            var eventBindingInfo = kv.Value;
                            var bStatic          = eventBindingInfo.isStatic;
                            //NOTE: 静态事件在绑定过程直接定义, 非静态事件推迟到构造时直接赋值创建
                            var tsFieldVar    = BindingManager.GetTSVariable(eventBindingInfo.regName);
                            var tsFieldType   = this.cg.bindingManager.GetTSTypeFullName(eventBindingInfo.eventInfo.EventHandlerType);
                            var tsFieldPrefix = "";
                            if (bStatic)
                            {
                                tsFieldPrefix += "static ";
                                cg.cs.AppendLine($"duk_add_event(ctx, \"{tsFieldVar}\", {eventBindingInfo.adderName}, {eventBindingInfo.removerName}, -2);");
                            }
                            else
                            {
                                cg.cs.AppendLine($"duk_add_property(ctx, \"{tsFieldVar}\", {eventBindingInfo.proxyName}, null, -1);");
                            }
                            cg.tsDeclare.AppendLine($"{tsFieldPrefix}{tsFieldVar}: DuktapeJS.event<{tsFieldType}>");
                        }
                        cg.cs.AppendLine("duk_end_class(ctx);");
                    }
                }
                base.Dispose();
            }

            this.cg.tsDeclare.DecTabLevel();
            this.cg.tsDeclare.AppendLine("}");
        }
Esempio n. 3
0
 public static void ClearBindings()
 {
     BindingManager.Cleanup(Prefs.Load(Prefs.PATH).outDir, null, null);
     AssetDatabase.Refresh();
 }
 public virtual void OnPostGenerateDelegate(BindingManager bindingManager, DelegateBindingInfo bindingInfo)
 {
 }
 public virtual void OnCleanup(BindingManager bindingManager)
 {
 }
 public virtual bool OnExportingType(BindingManager bindingManager, Type type)
 {
     return(false);
 }
 public virtual void OnPostGenerateType(BindingManager bindingManager, TypeBindingInfo bindingInfo)
 {
 }
 public virtual void OnPostCollectTypes(BindingManager bindingManager)
 {
 }
 public virtual void OnPostExporting(BindingManager bindingManager)
 {
 }
 public virtual void OnPostCollectAssemblies(BindingManager bindingManager)
 {
 }
 public virtual void OnInitialize(BindingManager bindingManager)
 {
 }
        protected List <ParameterInfo> WriteTSDeclaration(T method, MethodBaseBindingInfo <T> bindingInfo)
        {
            var    isExtension   = method.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute));
            var    refParameters = new List <ParameterInfo>();
            string tsMethodDeclaration;

            this.cg.AppendJSDoc(method);
            if (this.cg.bindingManager.GetTSMethodDeclaration(method, out tsMethodDeclaration))
            {
                this.cg.tsDeclare.AppendLine(tsMethodDeclaration);
                return(refParameters);
            }
            var isRaw = method.IsDefined(typeof(JSCFunctionAttribute));
            //TODO: 需要处理参数类型归并问题, 因为如果类型没有导入 ts 中, 可能会在声明中出现相同参数列表的定义
            //      在 MethodVariant 中创建每个方法对应的TS类型名参数列表, 完全相同的不再输出
            var prefix = "";

            if (method.IsStatic && !isExtension)
            {
                prefix = "static ";
            }
            string tsMethodRename;

            if (this.cg.bindingManager.GetTSMethodRename(method, out tsMethodRename))
            {
                this.cg.tsDeclare.Append($"{prefix}{tsMethodRename}(");
            }
            else
            {
                this.cg.tsDeclare.Append($"{prefix}{bindingInfo.regName}(");
            }

            if (isRaw)
            {
                this.cg.tsDeclare.AppendL("...uncertain: any[]): any /* uncertain */");
                this.cg.tsDeclare.AppendLine();
            }
            else
            {
                var parameters = method.GetParameters();
                if (isExtension)
                {
                    ArrayUtility.RemoveAt(ref parameters, 0);
                }
                for (var i = 0; i < parameters.Length; i++)
                {
                    var parameter        = parameters[i];
                    var parameter_prefix = "";
                    var parameterType    = parameter.ParameterType;
                    if (parameter.IsOut && parameterType.IsByRef)
                    {
                        // parameter_prefix = "/*out*/ ";
                        refParameters.Add(parameter);
                    }
                    else if (parameterType.IsByRef)
                    {
                        // parameter_prefix = "/*ref*/ ";
                        refParameters.Add(parameter);
                    }
                    if (parameter.IsDefined(typeof(ParamArrayAttribute), false) && i == parameters.Length - 1)
                    {
                        var elementType      = parameterType.GetElementType();
                        var elementTS        = this.cg.bindingManager.GetTSTypeFullName(elementType);
                        var parameterVarName = BindingManager.GetTSVariable(parameter.Name);
                        this.cg.tsDeclare.AppendL($"{parameter_prefix}...{parameterVarName}: {elementTS}[]");
                    }
                    else
                    {
                        var parameterTS      = this.cg.bindingManager.GetTSTypeFullName(parameterType, parameter.IsOut);
                        var parameterVarName = BindingManager.GetTSVariable(parameter.Name);
                        this.cg.tsDeclare.AppendL($"{parameter_prefix}{parameterVarName}: {parameterTS}");
                    }
                    if (i != parameters.Length - 1)
                    {
                        this.cg.tsDeclare.AppendL(", ");
                    }
                }
                this.cg.tsDeclare.AppendL($")");
                WriteTSReturn(method, refParameters);
            }
            return(refParameters);
        }